@airframes/acars-decoder 1.8.9 → 1.8.11

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.mjs CHANGED
@@ -1809,10 +1809,18 @@ var Label_16_TOD = class extends DecoderPlugin {
1809
1809
  ResultFormatter.unknown(decodeResult, fields[3]);
1810
1810
  const temp = fields[4].split("/");
1811
1811
  const posFields = temp[0].split(" ");
1812
- ResultFormatter.position(decodeResult, {
1813
- latitude: CoordinateUtils.getDirection(posFields[0]) * Number(posFields[1]),
1814
- longitude: CoordinateUtils.getDirection(posFields[2]) * Number(posFields[3])
1815
- });
1812
+ if (posFields.length === 4) {
1813
+ ResultFormatter.position(decodeResult, {
1814
+ latitude: CoordinateUtils.getDirection(posFields[0]) * Number(posFields[1]),
1815
+ longitude: CoordinateUtils.getDirection(posFields[2]) * Number(posFields[3])
1816
+ });
1817
+ } else if (posFields.length === 2) {
1818
+ ResultFormatter.position(decodeResult, {
1819
+ latitude: CoordinateUtils.getDirection(posFields[0][0]) * Number(posFields[0].slice(1)) / 100,
1820
+ longitude: CoordinateUtils.getDirection(posFields[1][0]) * Number(posFields[1].slice(1)) / 100
1821
+ });
1822
+ } else {
1823
+ }
1816
1824
  if (temp.length > 1) {
1817
1825
  ResultFormatter.flightNumber(decodeResult, temp[1]);
1818
1826
  }
@@ -1822,691 +1830,362 @@ var Label_16_TOD = class extends DecoderPlugin {
1822
1830
  }
1823
1831
  };
1824
1832
 
1825
- // lib/utils/flight_plan_utils.ts
1826
- var FlightPlanUtils = class _FlightPlanUtils {
1827
- /**
1828
- * Processes flight plan data
1829
- *
1830
- * Expected format is [header, key1, val1, ... keyN, valN]
1831
- *
1832
- * @param decodeResult - results
1833
- * @param data - original message split by ':'
1834
- * @returns whether all fields were processed or not
1835
- */
1836
- static processFlightPlan(decodeResult, data) {
1837
- let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
1838
- for (let i = 1; i < data.length; i += 2) {
1839
- const key = data[i];
1840
- const value = data[i + 1];
1841
- switch (key) {
1842
- case "A":
1843
- _FlightPlanUtils.addProcedure(decodeResult, value, "arrival");
1844
- break;
1845
- case "AA":
1846
- addArrivalAirport(decodeResult, value);
1847
- break;
1848
- case "AP":
1849
- _FlightPlanUtils.addProcedure(decodeResult, value, "approach");
1850
- break;
1851
- case "CR":
1852
- addCompanyRoute(decodeResult, value);
1853
- break;
1854
- case "D":
1855
- _FlightPlanUtils.addProcedure(decodeResult, value, "departure");
1856
- break;
1857
- case "DA":
1858
- addDepartureAirport(decodeResult, value);
1859
- break;
1860
- case "F":
1861
- addRoute(decodeResult, value);
1862
- break;
1863
- case "FP":
1864
- ResultFormatter.flightPlan(decodeResult, value.trim());
1865
- break;
1866
- case "R":
1867
- addRunway(decodeResult, value);
1868
- break;
1869
- // case 'WS': // something about routes, has altitude, so current parsing won't work
1870
- // break;
1871
- default:
1872
- if (allKnownFields) {
1873
- decodeResult.remaining.text = "";
1874
- allKnownFields = false;
1875
- }
1876
- decodeResult.remaining.text += `:${key}:${value}`;
1877
- decodeResult.decoder.decodeLevel = "partial";
1878
- }
1879
- }
1880
- return allKnownFields;
1833
+ // lib/plugins/Label_1M_Slash.ts
1834
+ var Label_1M_Slash = class extends DecoderPlugin {
1835
+ name = "label-1m-slash";
1836
+ qualifiers() {
1837
+ return {
1838
+ labels: ["1M"],
1839
+ preambles: ["/"]
1840
+ };
1881
1841
  }
1882
- static parseHeader(decodeResult, header) {
1883
- let allKnownFields = true;
1884
- if (header.startsWith("RF")) {
1885
- decodeResult.formatted.items.push({
1886
- type: "status",
1887
- code: "ROUTE_STATUS",
1888
- label: "Route Status",
1889
- value: "Route Filed"
1890
- });
1891
- decodeResult.raw.route_status = "RF";
1892
- if (header.length > 2) {
1893
- addRoute(decodeResult, header.substring(2));
1842
+ decode(message, options = {}) {
1843
+ const decodeResult = this.defaultResult();
1844
+ decodeResult.decoder.name = this.name;
1845
+ decodeResult.formatted.description = "ETA Report";
1846
+ decodeResult.message = message;
1847
+ const results = message.text.split(/\n|\//).slice(1);
1848
+ if (results) {
1849
+ if (options.debug) {
1850
+ console.log("Label 1M ETA: results");
1851
+ console.log(results);
1894
1852
  }
1895
- } else if (header.startsWith("RP")) {
1896
- decodeResult.raw.route_status = "RP";
1897
- decodeResult.formatted.items.push({
1898
- type: "status",
1899
- code: "ROUTE_STATUS",
1900
- label: "Route Status",
1901
- value: "Route Planned"
1902
- });
1903
- decodeResult.raw.route_status = header;
1904
- } else if (header.startsWith("RI")) {
1905
- decodeResult.raw.route_status = "RI";
1906
- decodeResult.formatted.items.push({
1907
- type: "status",
1908
- code: "ROUTE_STATUS",
1909
- label: "Route Status",
1910
- value: "Route Inactive"
1911
- });
1912
- } else if (header.startsWith("RM")) {
1913
- decodeResult.raw.route_status = "RM";
1914
- decodeResult.formatted.items.push({
1915
- type: "status",
1916
- code: "ROUTE_STATUS",
1917
- label: "Route Status",
1918
- value: "Route Mapped"
1919
- });
1920
- } else if (header.startsWith("RS")) {
1921
- decodeResult.raw.route_status = "RS";
1922
- decodeResult.formatted.items.push({
1923
- type: "status",
1924
- code: "ROUTE_STATUS",
1925
- label: "Route Status",
1926
- value: "Route Saved"
1927
- });
1928
- } else {
1929
- decodeResult.remaining.text += header;
1930
- allKnownFields = false;
1931
- }
1932
- return allKnownFields;
1933
- }
1934
- static addProcedure(decodeResult, value, type) {
1935
- if (decodeResult.raw.procedures === void 0) {
1936
- decodeResult.raw.procedures = [];
1937
- }
1938
- const data = value.split(".");
1939
- let waypoints;
1940
- if (data.length > 1) {
1941
- waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1853
+ decodeResult.raw.flight_number = results[0];
1854
+ ResultFormatter.departureAirport(decodeResult, results[3]);
1855
+ ResultFormatter.arrivalAirport(decodeResult, results[4]);
1856
+ ResultFormatter.alternateAirport(decodeResult, results[5]);
1857
+ ResultFormatter.arrivalRunway(
1858
+ decodeResult,
1859
+ results[8].replace(results[4], "")
1860
+ );
1861
+ const yymmdd = results[2];
1862
+ ResultFormatter.eta(
1863
+ decodeResult,
1864
+ DateTimeUtils.convertDateTimeToEpoch(
1865
+ results[7] + "00",
1866
+ yymmdd.substring(4, 6) + yymmdd.substring(2, 4) + yymmdd.substring(0, 2)
1867
+ ),
1868
+ "epoch"
1869
+ );
1942
1870
  }
1943
- const route = { name: data[0], waypoints };
1944
- decodeResult.raw.procedures.push({ type, route });
1945
- const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
1946
- decodeResult.formatted.items.push({
1947
- type: "procedure",
1948
- code: "proc",
1949
- label: `${procedureName} Procedure`,
1950
- value: RouteUtils.routeToString(route)
1951
- });
1871
+ decodeResult.decoded = true;
1872
+ decodeResult.decoder.decodeLevel = "partial";
1873
+ return decodeResult;
1952
1874
  }
1953
1875
  };
1954
- function addArrivalAirport(decodeResult, value) {
1955
- ResultFormatter.arrivalAirport(decodeResult, value);
1956
- }
1957
- function addDepartureAirport(decodeResult, value) {
1958
- ResultFormatter.departureAirport(decodeResult, value);
1959
- }
1960
- function addRunway(decodeResult, value) {
1961
- if (value.length === 8) {
1962
- ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1963
- }
1964
- ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1965
- }
1966
- function addRoute(decodeResult, value) {
1967
- const route = value.split(".");
1968
- ResultFormatter.route(decodeResult, {
1969
- waypoints: route.map((leg) => RouteUtils.getWaypoint(leg))
1970
- });
1971
- }
1972
- function addCompanyRoute(decodeResult, value) {
1973
- const segments = value.split(".");
1974
- const parens_idx = segments[0].indexOf("(");
1975
- let name;
1976
- let runway;
1977
- if (parens_idx === -1) {
1978
- name = segments[0];
1979
- } else {
1980
- name = segments[0].slice(0, parens_idx);
1981
- runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
1982
- }
1983
- let waypoints;
1984
- if (segments.length > 1) {
1985
- waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1986
- }
1987
- decodeResult.raw.company_route = {
1988
- name,
1989
- runway,
1990
- waypoints
1991
- };
1992
- decodeResult.formatted.items.push({
1993
- type: "company_route",
1994
- code: "CR",
1995
- label: "Company Route",
1996
- value: RouteUtils.routeToString(decodeResult.raw.company_route)
1997
- });
1998
- }
1999
1876
 
2000
- // lib/utils/h1_helper.ts
2001
- var H1Helper = class _H1Helper {
2002
- static decodeH1Message(decodeResult, message) {
2003
- const checksum = parseInt(message.slice(-4), 16);
2004
- const data = message.slice(0, message.length - 4);
2005
- let checksumAlgorithmUsed = "";
2006
- if (crc16IbmSdlcRev(data) === checksum) {
2007
- checksumAlgorithmUsed = "IBM-SDLC reversed";
2008
- } else if (crc16Genibus(data) === checksum) {
2009
- checksumAlgorithmUsed = "GENIBUS";
2010
- } else {
2011
- decodeResult.decoded = false;
2012
- decodeResult.decoder.decodeLevel = "none";
2013
- return false;
2014
- }
2015
- const fields = data.split("/");
2016
- const canDecode = parseMessageType(decodeResult, fields[0]);
2017
- if (!canDecode) {
1877
+ // lib/plugins/Label_1L_3-line.ts
1878
+ var Label_1L_3Line = class extends DecoderPlugin {
1879
+ name = "label-1l-3-line";
1880
+ qualifiers() {
1881
+ return {
1882
+ labels: ["1L"]
1883
+ };
1884
+ }
1885
+ decode(message, options = {}) {
1886
+ const decodeResult = this.defaultResult();
1887
+ decodeResult.decoder.name = this.name;
1888
+ decodeResult.formatted.description = "Position Report";
1889
+ decodeResult.message = message;
1890
+ const lines = message.text.split("\r\n");
1891
+ if (lines.length !== 3) {
1892
+ if (options.debug) {
1893
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1894
+ }
1895
+ decodeResult.remaining.text = message.text;
2018
1896
  decodeResult.decoded = false;
2019
1897
  decodeResult.decoder.decodeLevel = "none";
2020
- return false;
1898
+ return decodeResult;
2021
1899
  }
2022
- for (let i = 1; i < fields.length; ++i) {
2023
- const key = fields[i].substring(0, 2);
2024
- const data2 = fields[i].substring(2);
2025
- switch (key) {
2026
- case "AF":
2027
- processAirField(decodeResult, data2.split(","));
2028
- break;
2029
- case "AK":
2030
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2031
- break;
2032
- case "CG":
2033
- processCenterOfGravity(decodeResult, data2.split(","));
2034
- break;
2035
- case "DC":
2036
- processDateCode(decodeResult, data2.split(","));
2037
- break;
2038
- case "DI":
2039
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2040
- break;
2041
- case "DT":
2042
- processDT(decodeResult, data2.split(","));
2043
- break;
2044
- case "DQ":
2045
- ResultFormatter.desiredAltitude(
2046
- decodeResult,
2047
- parseInt(data2, 10) * 100
2048
- );
2049
- break;
2050
- case "ET":
2051
- processETA(data2, decodeResult, fields, i);
2052
- break;
2053
- case "FB":
2054
- ResultFormatter.currentFuel(decodeResult, parseInt(data2, 10));
2055
- break;
2056
- case "FN":
2057
- decodeResult.raw.flight_number = data2;
2058
- break;
2059
- case "FX":
2060
- ResultFormatter.freetext(decodeResult, data2);
2061
- break;
2062
- case "GA":
2063
- ResultFormatter.groundAddress(decodeResult, data2);
2064
- break;
2065
- case "ID":
2066
- processIdentification(decodeResult, data2.split(","));
2067
- break;
2068
- case "LR":
2069
- processLandingReport(decodeResult, data2.split(","));
2070
- break;
2071
- case "PR":
2072
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2073
- break;
2074
- case "PS":
2075
- _H1Helper.processPS(decodeResult, data2.split(","));
2076
- break;
2077
- case "RF":
2078
- case "RI":
2079
- case "RM":
2080
- case "RP":
2081
- case "RS":
2082
- FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
2083
- break;
2084
- case "RN":
2085
- ResultFormatter.routeNumber(decodeResult, data2);
2086
- break;
2087
- case "RW":
2088
- processRunway(decodeResult, data2.split(":"));
2089
- break;
2090
- case "SN":
2091
- decodeResult.raw.serial_number = data2;
2092
- break;
2093
- case "SP":
2094
- ResultFormatter.startPoint(decodeResult, data2);
2095
- break;
2096
- case "TD":
2097
- processTimeOfDeparture(decodeResult, data2.split(","));
2098
- break;
2099
- case "TS":
2100
- _H1Helper.processTimeStamp(decodeResult, data2.split(","));
2101
- break;
2102
- case "VR":
2103
- ResultFormatter.version(decodeResult, parseInt(data2, 10) / 10);
2104
- break;
2105
- case "WD":
2106
- processWindData(decodeResult, data2);
2107
- break;
2108
- case "WQ":
2109
- processWeatherQuery(decodeResult, data2.split(":"));
2110
- break;
2111
- default:
2112
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2113
- }
1900
+ const parts = message.text.replaceAll("\r\n", "/").split("/");
1901
+ const data = /* @__PURE__ */ new Map();
1902
+ data.set("", parts[0]);
1903
+ for (let i = 1; i < parts.length; i++) {
1904
+ const part = parts[i].split(" ");
1905
+ data.set(part[0], part.slice(1).join(" "));
2114
1906
  }
2115
- ResultFormatter.checksumAlgorithm(decodeResult, checksumAlgorithmUsed);
2116
- ResultFormatter.checksum(decodeResult, checksum);
2117
- return true;
2118
- }
2119
- static processPS(decodeResult, data) {
2120
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2121
- data[0]
2122
- );
2123
- if (position) {
2124
- ResultFormatter.position(decodeResult, position);
1907
+ const dep = data.get("DEP");
1908
+ if (dep) {
1909
+ ResultFormatter.departureAirport(decodeResult, dep);
1910
+ data.delete("DEP");
2125
1911
  }
2126
- if (data.length === 9) {
2127
- processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
2128
- ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
2129
- ResultFormatter.temperature(decodeResult, data[6]);
2130
- ResultFormatter.unknown(decodeResult, data[7]);
2131
- ResultFormatter.unknown(decodeResult, data[8]);
1912
+ const des = data.get("DES");
1913
+ if (des) {
1914
+ ResultFormatter.arrivalAirport(decodeResult, des);
1915
+ data.delete("DES");
2132
1916
  }
2133
- if (data.length === 14) {
2134
- ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
2135
- processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
2136
- ResultFormatter.temperature(decodeResult, data[7]);
2137
- ResultFormatter.unknownArr(decodeResult, data.slice(8));
1917
+ const eta = data.get("ETA");
1918
+ if (eta) {
1919
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
1920
+ data.delete("ETA");
2138
1921
  }
2139
- }
2140
- static processPosition(decodeResult, data) {
2141
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2142
- data[0]
2143
- );
2144
- if (position) {
2145
- ResultFormatter.position(decodeResult, position);
1922
+ const alt = data.get("ALT");
1923
+ if (alt) {
1924
+ ResultFormatter.altitude(decodeResult, Number(alt));
1925
+ data.delete("ALT");
2146
1926
  }
2147
- if (data.length >= 10) {
2148
- ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
2149
- processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
2150
- ResultFormatter.temperature(decodeResult, data[7]);
2151
- ResultFormatter.unknown(decodeResult, data[8]);
2152
- ResultFormatter.unknown(decodeResult, data[9]);
1927
+ const fn = data.get("FN");
1928
+ if (fn) {
1929
+ ResultFormatter.flightNumber(decodeResult, fn);
1930
+ data.delete("FN");
2153
1931
  }
2154
- if (data.length >= 14) {
2155
- ResultFormatter.unknownArr(decodeResult, data.slice(10));
1932
+ const day = data.get("DAY");
1933
+ const utc = data.get("UTC");
1934
+ if (day && utc) {
1935
+ decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
1936
+ data.delete("DAY");
1937
+ data.delete("UTC");
2156
1938
  }
2157
- }
2158
- static processTimeStamp(decodeResult, data) {
2159
- if (data.length > 2) {
2160
- const positionData = data.slice(1);
2161
- positionData[0] = positionData[0].substring(6);
2162
- this.processPosition(decodeResult, positionData);
1939
+ const lat = data.get("LAT");
1940
+ const lon = data.get("LON");
1941
+ if (lat && lon) {
1942
+ ResultFormatter.position(decodeResult, {
1943
+ latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
1944
+ longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
1945
+ });
1946
+ data.delete("LAT");
1947
+ data.delete("LON");
2163
1948
  }
2164
- let time = DateTimeUtils.convertDateTimeToEpoch(
2165
- data[0],
2166
- data[1].substring(0, 6)
2167
- );
2168
- if (Number.isNaN(time)) {
2169
- const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
2170
- time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
1949
+ let remaining = "";
1950
+ for (const [key, value] of data.entries()) {
1951
+ if (key === "") {
1952
+ remaining += value;
1953
+ } else {
1954
+ remaining += `/${key} ${value}`;
1955
+ }
2171
1956
  }
2172
- decodeResult.raw.message_timestamp = time;
1957
+ decodeResult.remaining.text = remaining;
1958
+ decodeResult.decoded = true;
1959
+ decodeResult.decoder.decodeLevel = "partial";
1960
+ return decodeResult;
2173
1961
  }
2174
1962
  };
2175
- function processETA(data, decodeResult, fields, i) {
2176
- if (data.length === 5) {
2177
- ResultFormatter.day(decodeResult, Number(data.substring(0, 1)));
2178
- ResultFormatter.eta(
1963
+
1964
+ // lib/plugins/Label_1L_070.ts
1965
+ var Label_1L_070 = class extends DecoderPlugin {
1966
+ name = "label-1l-070";
1967
+ qualifiers() {
1968
+ return {
1969
+ labels: ["1L"],
1970
+ preambles: ["000000070"]
1971
+ };
1972
+ }
1973
+ decode(message, options = {}) {
1974
+ const decodeResult = this.defaultResult();
1975
+ decodeResult.decoder.name = this.name;
1976
+ decodeResult.formatted.description = "Position Report";
1977
+ decodeResult.message = message;
1978
+ if (!message.text.startsWith("000000070")) {
1979
+ if (options.debug) {
1980
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1981
+ }
1982
+ decodeResult.remaining.text = message.text;
1983
+ decodeResult.decoded = false;
1984
+ decodeResult.decoder.decodeLevel = "none";
1985
+ return decodeResult;
1986
+ }
1987
+ const parts = message.text.substring(9).split(",");
1988
+ if (parts.length !== 7) {
1989
+ if (options.debug) {
1990
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1991
+ }
1992
+ decodeResult.remaining.text = message.text;
1993
+ decodeResult.decoded = false;
1994
+ decodeResult.decoder.decodeLevel = "none";
1995
+ return decodeResult;
1996
+ }
1997
+ ResultFormatter.departureAirport(decodeResult, parts[0]);
1998
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
1999
+ ResultFormatter.time_of_day(
2179
2000
  decodeResult,
2180
- DateTimeUtils.convertHHMMSSToTod(data.substring(1))
2001
+ DateTimeUtils.convertHHMMSSToTod(parts[2])
2181
2002
  );
2182
- } else if (data.length === 6) {
2183
- ResultFormatter.day(decodeResult, Number(data.substring(0, 2)));
2184
2003
  ResultFormatter.eta(
2185
2004
  decodeResult,
2186
- DateTimeUtils.convertHHMMSSToTod(data.substring(2))
2005
+ DateTimeUtils.convertHHMMSSToTod(parts[3])
2187
2006
  );
2188
- } else {
2189
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2007
+ ResultFormatter.position(decodeResult, {
2008
+ latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
2009
+ longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
2010
+ });
2011
+ decodeResult.remaining.text = parts[6];
2012
+ decodeResult.decoded = true;
2013
+ decodeResult.decoder.decodeLevel = "partial";
2014
+ return decodeResult;
2190
2015
  }
2191
- }
2192
- function processAirField(decodeResult, data) {
2193
- if (data.length === 2) {
2194
- ResultFormatter.departureAirport(decodeResult, data[0]);
2195
- ResultFormatter.arrivalAirport(decodeResult, data[1]);
2196
- } else {
2197
- ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
2198
- }
2199
- }
2200
- function processTimeOfDeparture(decodeResult, data) {
2201
- if (data.length === 2) {
2202
- decodeResult.raw.plannedDepartureTime = data[0];
2203
- decodeResult.formatted.items.push({
2204
- type: "ptd",
2205
- code: "ptd",
2206
- label: "Planned Departure Time",
2207
- value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
2208
- });
2209
- decodeResult.raw.plannedDepartureTime = data[1];
2210
- decodeResult.formatted.items.push({
2211
- type: "etd",
2212
- code: "etd",
2213
- label: "Estimated Departure Time",
2214
- value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
2215
- });
2216
- } else {
2217
- ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
2218
- }
2219
- }
2220
- function processIdentification(decodeResult, data) {
2221
- ResultFormatter.tail(decodeResult, data[0]);
2222
- if (data.length > 1) {
2223
- ResultFormatter.flightNumber(decodeResult, data[1]);
2224
- }
2225
- if (data.length > 2) {
2226
- decodeResult.raw.mission_number = data[2];
2016
+ };
2017
+
2018
+ // lib/plugins/Label_1L_660.ts
2019
+ var Label_1L_660 = class extends DecoderPlugin {
2020
+ name = "label-1l-660";
2021
+ qualifiers() {
2022
+ return {
2023
+ labels: ["1L"],
2024
+ preambles: ["000000660"]
2025
+ };
2227
2026
  }
2228
- }
2229
- function processDT(decodeResult, data) {
2230
- if (data.length === 9) {
2231
- ResultFormatter.unknown(decodeResult, data[0]);
2232
- if (!decodeResult.raw.arrival_icao) {
2233
- ResultFormatter.arrivalAirport(decodeResult, data[1]);
2027
+ decode(message, options = {}) {
2028
+ const decodeResult = this.defaultResult();
2029
+ decodeResult.decoder.name = this.name;
2030
+ decodeResult.formatted.description = "Position Report";
2031
+ decodeResult.message = message;
2032
+ if (!message.text.startsWith("000000660")) {
2033
+ if (options.debug) {
2034
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
2035
+ }
2036
+ decodeResult.remaining.text = message.text;
2037
+ decodeResult.decoded = false;
2038
+ decodeResult.decoder.decodeLevel = "none";
2039
+ return decodeResult;
2234
2040
  }
2235
- ResultFormatter.arrivalRunway(decodeResult, data[2]);
2236
- ResultFormatter.currentFuel(decodeResult, parseInt(data[3], 10));
2237
- ResultFormatter.eta(
2238
- decodeResult,
2239
- DateTimeUtils.convertHHMMSSToTod(data[4])
2240
- );
2241
- ResultFormatter.unknown(decodeResult, data[5]);
2242
- ResultFormatter.position(
2243
- decodeResult,
2244
- CoordinateUtils.decodeStringCoordinates(data[6])
2041
+ const parts = message.text.substring(9).split(",");
2042
+ if (parts.length !== 5) {
2043
+ if (options.debug) {
2044
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
2045
+ }
2046
+ decodeResult.remaining.text = message.text;
2047
+ decodeResult.decoded = false;
2048
+ decodeResult.decoder.decodeLevel = "none";
2049
+ return decodeResult;
2050
+ }
2051
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2052
+ parts[0]
2245
2053
  );
2246
- ResultFormatter.unknown(decodeResult, data[7]);
2247
- ResultFormatter.unknown(decodeResult, data[8]);
2248
- return;
2249
- }
2250
- if (data.length === 4 || data.length === 5) {
2251
- if (!decodeResult.raw.arrival_icao) {
2252
- ResultFormatter.arrivalAirport(decodeResult, data[0]);
2054
+ if (position) {
2055
+ ResultFormatter.position(decodeResult, position);
2253
2056
  }
2254
- ResultFormatter.arrivalRunway(decodeResult, data[1]);
2255
- ResultFormatter.currentFuel(decodeResult, parseInt(data[2], 10));
2256
- ResultFormatter.eta(
2057
+ const hhmmss = parts[1].substring(0, 6);
2058
+ ResultFormatter.time_of_day(
2257
2059
  decodeResult,
2258
- DateTimeUtils.convertHHMMSSToTod(data[3])
2060
+ DateTimeUtils.convertHHMMSSToTod(hhmmss)
2259
2061
  );
2260
- if (data.length > 4) {
2261
- ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
2262
- }
2263
- return;
2062
+ const fl = parts[1].substring(6, 9);
2063
+ ResultFormatter.altitude(decodeResult, Number(fl) * 100);
2064
+ const next = parts[1].substring(9);
2065
+ ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
2066
+ decodeResult.remaining.text = parts.slice(2).join(",");
2067
+ decodeResult.decoded = true;
2068
+ decodeResult.decoder.decodeLevel = "partial";
2069
+ return decodeResult;
2264
2070
  }
2265
- ResultFormatter.unknownArr(decodeResult, data, ",");
2266
- }
2267
- function processLandingReport(decodeResult, data) {
2268
- if (data.length === 19) {
2269
- ResultFormatter.unknown(decodeResult, data[1]);
2270
- ResultFormatter.flightNumber(decodeResult, data[2]);
2271
- ResultFormatter.departureAirport(decodeResult, data[3]);
2272
- ResultFormatter.arrivalAirport(decodeResult, data[4]);
2273
- ResultFormatter.arrivalRunway(decodeResult, data[5]);
2274
- ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
2275
- } else {
2276
- ResultFormatter.unknown(decodeResult, data.join(","));
2071
+ };
2072
+
2073
+ // lib/plugins/Label_1L_Slash.ts
2074
+ var Label_1L_Slash = class extends DecoderPlugin {
2075
+ name = "label-1l-1-line";
2076
+ qualifiers() {
2077
+ return {
2078
+ labels: ["1L"],
2079
+ preambles: ["+", "-"]
2080
+ };
2277
2081
  }
2278
- }
2279
- function processCenterOfGravity(decodeResult, data) {
2280
- if (data.length === 1) {
2281
- if (data[0] !== void 0 && data[0] !== "") {
2282
- ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10);
2283
- }
2284
- } else if (data.length === 3) {
2285
- if (data[0] !== void 0 && data[0] !== "") {
2286
- ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10, "center");
2287
- }
2288
- if (data[1] !== void 0 && data[1] !== "") {
2289
- ResultFormatter.cg(decodeResult, parseInt(data[1], 10) / 10, "lower");
2082
+ decode(message, options = {}) {
2083
+ const decodeResult = this.defaultResult();
2084
+ decodeResult.decoder.name = this.name;
2085
+ decodeResult.formatted.description = "Position Report";
2086
+ decodeResult.message = message;
2087
+ const parts = message.text.split("/");
2088
+ if (parts.length !== 7) {
2089
+ if (options.debug) {
2090
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
2091
+ }
2092
+ decodeResult.remaining.text = message.text;
2093
+ decodeResult.decoded = false;
2094
+ decodeResult.decoder.decodeLevel = "none";
2095
+ return decodeResult;
2290
2096
  }
2291
- if (data[2] !== void 0 && data[2] !== "") {
2292
- ResultFormatter.cg(decodeResult, parseInt(data[2], 10) / 10, "upper");
2097
+ const data = /* @__PURE__ */ new Map();
2098
+ data.set("LAT", parts[0].replaceAll(" ", ""));
2099
+ data.set("LON", parts[1].replaceAll(" ", ""));
2100
+ for (let i = 2; i < parts.length; i++) {
2101
+ const part = parts[i].split(" ");
2102
+ data.set(part[0], part.slice(1).join(" "));
2293
2103
  }
2294
- } else {
2295
- ResultFormatter.unknown(decodeResult, data.join(","));
2296
- }
2297
- }
2298
- function parseMessageType(decodeResult, messagePart) {
2299
- const messageParts = messagePart.split(",");
2300
- const messageType = messageParts[0];
2301
- if (messageType.startsWith("POS")) {
2302
- H1Helper.processPosition(decodeResult, messagePart.substring(3).split(","));
2303
- return processMessageType(decodeResult, "POS");
2304
- } else if (messageType.length === 6) {
2305
- const part1 = processMessageType(decodeResult, messageType.substring(0, 3));
2306
- const description = decodeResult.formatted.description;
2307
- const part2 = processMessageType(decodeResult, messageType.substring(3, 6));
2308
- decodeResult.formatted.description = description + " for " + decodeResult.formatted.description;
2309
- if (messageParts.length > 1) {
2310
- ResultFormatter.unknown(
2104
+ const position = {
2105
+ latitude: Number(data.get("LAT")),
2106
+ longitude: Number(data.get("LON"))
2107
+ };
2108
+ data.delete("LAT");
2109
+ data.delete("LON");
2110
+ ResultFormatter.position(decodeResult, position);
2111
+ const utc = data.get("UTC");
2112
+ if (utc) {
2113
+ ResultFormatter.time_of_day(
2311
2114
  decodeResult,
2312
- messageParts.slice(1).join(","),
2313
- "/"
2115
+ DateTimeUtils.convertHHMMSSToTod(utc)
2314
2116
  );
2117
+ data.delete("UTC");
2315
2118
  }
2316
- return part1 && part2;
2119
+ const alt = data.get("ALT");
2120
+ if (alt) {
2121
+ ResultFormatter.altitude(decodeResult, Number(alt));
2122
+ data.delete("ALT");
2123
+ }
2124
+ const fob = data.get("FOB");
2125
+ if (fob) {
2126
+ ResultFormatter.currentFuel(decodeResult, Number(fob));
2127
+ data.delete("FOB");
2128
+ }
2129
+ const eta = data.get("ETA");
2130
+ if (eta) {
2131
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
2132
+ data.delete("ETA");
2133
+ }
2134
+ let remaining = "";
2135
+ for (const [key, value] of data.entries()) {
2136
+ remaining += `/${key} ${value}`;
2137
+ }
2138
+ decodeResult.remaining.text = remaining;
2139
+ decodeResult.decoded = true;
2140
+ decodeResult.decoder.decodeLevel = "partial";
2141
+ return decodeResult;
2317
2142
  }
2318
- if (messageParts.length > 1) {
2319
- ResultFormatter.unknown(decodeResult, messageParts.slice(1).join(","), "/");
2143
+ };
2144
+
2145
+ // lib/plugins/Label_20_POS.ts
2146
+ var Label_20_POS = class extends DecoderPlugin {
2147
+ name = "label-20-pos";
2148
+ qualifiers() {
2149
+ return {
2150
+ labels: ["20"],
2151
+ preambles: ["POS"]
2152
+ };
2320
2153
  }
2321
- return processMessageType(decodeResult, messageType);
2322
- }
2323
- function processMessageType(decodeResult, type) {
2324
- if (type === "FPN") {
2325
- decodeResult.formatted.description = "Flight Plan";
2326
- } else if (type === "FTX") {
2327
- decodeResult.formatted.description = "Free Text";
2328
- } else if (type === "INI") {
2329
- decodeResult.formatted.description = "Initial Report";
2330
- } else if (type === "INR") {
2331
- decodeResult.formatted.description = "In-Range Report";
2332
- } else if (type === "LDI") {
2333
- decodeResult.formatted.description = "Load Distribution Information";
2334
- } else if (type === "PER") {
2335
- decodeResult.formatted.description = "Performance Report";
2336
- } else if (type === "POS") {
2154
+ decode(message, options = {}) {
2155
+ const decodeResult = this.defaultResult();
2156
+ decodeResult.decoder.name = this.name;
2337
2157
  decodeResult.formatted.description = "Position Report";
2338
- } else if (type === "PRG") {
2339
- decodeResult.formatted.description = "Progress Report";
2340
- } else if (type === "PWI") {
2341
- decodeResult.formatted.description = "Pilot Weather Information";
2342
- } else if (type === "WXR") {
2343
- decodeResult.formatted.description = "Weather Report";
2344
- } else if (type === "REJ") {
2345
- decodeResult.formatted.description = "Reject";
2346
- } else if (type === "REQ") {
2347
- decodeResult.formatted.description = "Request";
2348
- } else if (type === "RES") {
2349
- decodeResult.formatted.description = "Response";
2350
- } else {
2351
- decodeResult.formatted.description = "Unknown H1 Message";
2352
- return false;
2353
- }
2354
- return true;
2355
- }
2356
- function processDateCode(decodeResult, data) {
2357
- if (data.length === 1) {
2358
- } else if (data.length === 2) {
2359
- const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
2360
- const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
2361
- decodeResult.raw.message_timestamp = time;
2362
- }
2363
- }
2364
- function processWeatherQuery(decodeResult, data) {
2365
- if (data.length !== 2) {
2366
- ResultFormatter.unknown(decodeResult, data.join(":"), "WQ/");
2367
- return;
2368
- }
2369
- const alts = data[0].split(".");
2370
- const route = data[1].split(".");
2371
- ResultFormatter.requestedAltitudes(
2372
- decodeResult,
2373
- alts.map((a) => parseInt(a, 10) * 100)
2374
- );
2375
- const waypoints = route.map((wp) => {
2376
- return { name: wp };
2377
- });
2378
- ResultFormatter.route(decodeResult, { waypoints });
2379
- }
2380
- function processRoute(decodeResult, last, time, next, eta, then, date) {
2381
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
2382
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
2383
- const timeFormat = date ? "epoch" : "tod";
2384
- const lastWaypoint = RouteUtils.getWaypoint(last);
2385
- lastWaypoint.time = lastTime;
2386
- lastWaypoint.timeFormat = timeFormat;
2387
- const nextWaypoint = RouteUtils.getWaypoint(next);
2388
- nextWaypoint.time = nextTime;
2389
- nextWaypoint.timeFormat = timeFormat;
2390
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
2391
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
2392
- ResultFormatter.route(decodeResult, { waypoints });
2393
- }
2394
- function processWindData(decodeResult, message) {
2395
- const wind = [];
2396
- const flightLevel = Number(message.slice(0, 3));
2397
- const fields = message.slice(4).split(".");
2398
- fields.forEach((field) => {
2399
- if (field.length < 4) {
2400
- return;
2401
- }
2402
- const data = field.split(",");
2403
- const waypoint = { name: data[0] };
2404
- const windData = data[1];
2405
- const windDirection = parseInt(windData.slice(0, 3), 10);
2406
- const windSpeed = parseInt(windData.slice(3), 10);
2407
- if (data.length === 3) {
2408
- const tempData = data[2];
2409
- const tempFlightLevel = Number(tempData.slice(0, 3));
2410
- const tempString = tempData.slice(3);
2411
- const tempDegrees = Number(tempString.substring(1)) * (tempString.charAt(0) === "M" ? -1 : 1);
2412
- wind.push({
2413
- waypoint,
2414
- flightLevel,
2415
- windDirection,
2416
- windSpeed,
2417
- temperature: {
2418
- flightLevel: tempFlightLevel,
2419
- degreesC: tempDegrees
2420
- }
2421
- });
2422
- } else {
2423
- wind.push({
2424
- waypoint,
2425
- flightLevel,
2426
- windDirection,
2427
- windSpeed
2428
- });
2429
- }
2430
- });
2431
- ResultFormatter.windData(decodeResult, wind);
2432
- }
2433
- function processRunway(decodeResult, data) {
2434
- const parts = data[0].split(".");
2435
- const more = parts[0].split(",");
2436
- ResultFormatter.departureRunway(decodeResult, more[0]);
2437
- ResultFormatter.unknownArr(decodeResult, more.slice(1), ",");
2438
- ResultFormatter.unknownArr(decodeResult, parts.slice(1), ".");
2439
- ResultFormatter.departureAirport(decodeResult, data[1].split(",")[0]);
2440
- ResultFormatter.unknownArr(decodeResult, data[1].split(",").slice(1), ",");
2441
- }
2442
- function crc16IbmSdlcRev(data) {
2443
- let crc = 65535;
2444
- const bytes = Buffer.from(data, "ascii");
2445
- for (const byte of bytes) {
2446
- crc ^= byte;
2447
- for (let i = 0; i < 8; i++) {
2448
- if ((crc & 1) !== 0) {
2449
- crc = crc >>> 1 ^ 33800;
2450
- } else {
2451
- crc = crc >>> 1;
2452
- }
2453
- }
2454
- }
2455
- crc = (crc ^ 65535) & 65535;
2456
- const nibble1 = crc >> 12 & 15;
2457
- const nibble2 = crc >> 8 & 15;
2458
- const nibble3 = crc >> 4 & 15;
2459
- const nibble4 = crc & 15;
2460
- return nibble4 << 12 | nibble3 << 8 | nibble2 << 4 | nibble1;
2461
- }
2462
- function crc16Genibus(data) {
2463
- let crc = 65535;
2464
- const polynomial = 4129;
2465
- const bytes = Buffer.from(data, "ascii");
2466
- for (const byte of bytes) {
2467
- crc ^= byte << 8;
2468
- for (let i = 0; i < 8; i++) {
2469
- if ((crc & 32768) !== 0) {
2470
- crc = (crc << 1 ^ polynomial) & 65535;
2471
- } else {
2472
- crc = crc << 1 & 65535;
2473
- }
2474
- }
2475
- }
2476
- return (crc ^ 65535) & 65535;
2477
- }
2478
-
2479
- // lib/plugins/Label_1J_2J_FTX.ts
2480
- var Label_1J_2J_FTX = class extends DecoderPlugin {
2481
- name = "label-1j-2j-ftx";
2482
- qualifiers() {
2483
- return {
2484
- labels: ["1J", "2J"]
2485
- };
2486
- }
2487
- decode(message, options = {}) {
2488
- let decodeResult = this.defaultResult();
2489
- decodeResult.decoder.name = this.name;
2490
2158
  decodeResult.message = message;
2491
- const msg = message.text.replace(/\n|\r/g, "");
2492
- const parts = msg.split("/");
2493
- let decoded = false;
2494
- if (parts[0].length > 3) {
2495
- decoded = H1Helper.decodeH1Message(
2159
+ decodeResult.raw.preamble = message.text.substring(0, 3);
2160
+ const content = message.text.substring(3);
2161
+ const fields = content.split(",");
2162
+ if (fields.length == 11) {
2163
+ if (options.debug) {
2164
+ console.log(`DEBUG: ${this.name}: Variation 1 detected`);
2165
+ }
2166
+ const rawCoords = fields[0];
2167
+ ResultFormatter.position(
2496
2168
  decodeResult,
2497
- msg.slice(parts[0].length - 3)
2169
+ CoordinateUtils.decodeStringCoordinates(rawCoords)
2498
2170
  );
2499
- decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
2171
+ decodeResult.decoded = true;
2172
+ decodeResult.decoder.decodeLevel = "full";
2173
+ } else if (fields.length == 5) {
2174
+ if (options.debug) {
2175
+ console.log(`DEBUG: ${this.name}: Variation 2 detected`);
2176
+ }
2177
+ const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
2178
+ if (position) {
2179
+ ResultFormatter.position(decodeResult, position);
2180
+ }
2181
+ decodeResult.decoded = true;
2182
+ decodeResult.decoder.decodeLevel = "full";
2500
2183
  } else {
2501
- decoded = H1Helper.decodeH1Message(decodeResult, msg);
2502
- }
2503
- decodeResult.decoded = decoded;
2504
- decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
2505
- if (decodeResult.formatted.items.length === 0) {
2506
2184
  if (options.debug) {
2507
- console.log(`Decoder: Unknown 1J/2J message: ${message.text}`);
2185
+ console.log(
2186
+ `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`
2187
+ );
2508
2188
  }
2509
- ResultFormatter.unknown(decodeResult, message.text);
2510
2189
  decodeResult.decoded = false;
2511
2190
  decodeResult.decoder.decodeLevel = "none";
2512
2191
  }
@@ -2514,144 +2193,183 @@ var Label_1J_2J_FTX = class extends DecoderPlugin {
2514
2193
  }
2515
2194
  };
2516
2195
 
2517
- // lib/plugins/Label_1M_Slash.ts
2518
- var Label_1M_Slash = class extends DecoderPlugin {
2519
- name = "label-1m-slash";
2196
+ // lib/plugins/Label_21_POS.ts
2197
+ var Label_21_POS = class extends DecoderPlugin {
2198
+ name = "label-21-pos";
2520
2199
  qualifiers() {
2521
2200
  return {
2522
- labels: ["1M"],
2523
- preambles: ["/"]
2201
+ labels: ["21"],
2202
+ preambles: ["POS"]
2524
2203
  };
2525
2204
  }
2526
2205
  decode(message, options = {}) {
2527
2206
  const decodeResult = this.defaultResult();
2528
2207
  decodeResult.decoder.name = this.name;
2529
- decodeResult.formatted.description = "ETA Report";
2208
+ decodeResult.formatted.description = "Position Report";
2530
2209
  decodeResult.message = message;
2531
- const results = message.text.split(/\n|\//).slice(1);
2532
- if (results) {
2533
- if (options.debug) {
2534
- console.log("Label 1M ETA: results");
2535
- console.log(results);
2536
- }
2537
- decodeResult.raw.flight_number = results[0];
2538
- ResultFormatter.departureAirport(decodeResult, results[3]);
2539
- ResultFormatter.arrivalAirport(decodeResult, results[4]);
2540
- ResultFormatter.alternateAirport(decodeResult, results[5]);
2541
- ResultFormatter.arrivalRunway(
2210
+ decodeResult.raw.preamble = message.text.substring(0, 3);
2211
+ const content = message.text.substring(3);
2212
+ const fields = content.split(",");
2213
+ if (fields.length == 9) {
2214
+ processPosition(decodeResult, fields[0].trim());
2215
+ ResultFormatter.time_of_day(
2542
2216
  decodeResult,
2543
- results[8].replace(results[4], "")
2217
+ DateTimeUtils.convertHHMMSSToTod(fields[2])
2544
2218
  );
2545
- const yymmdd = results[2];
2219
+ ResultFormatter.altitude(decodeResult, Number(fields[3]));
2220
+ ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
2546
2221
  ResultFormatter.eta(
2547
2222
  decodeResult,
2548
- DateTimeUtils.convertDateTimeToEpoch(
2549
- results[7] + "00",
2550
- yymmdd.substring(4, 6) + yymmdd.substring(2, 4) + yymmdd.substring(0, 2)
2551
- ),
2552
- "epoch"
2223
+ DateTimeUtils.convertHHMMSSToTod(fields[7])
2553
2224
  );
2225
+ ResultFormatter.arrivalAirport(decodeResult, fields[8]);
2226
+ ResultFormatter.unknownArr(decodeResult, [
2227
+ fields[1],
2228
+ fields[4],
2229
+ fields[5]
2230
+ ]);
2231
+ decodeResult.decoded = true;
2232
+ decodeResult.decoder.decodeLevel = "partial";
2233
+ } else {
2234
+ if (options.debug) {
2235
+ console.log(
2236
+ `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`
2237
+ );
2238
+ }
2239
+ decodeResult.decoded = false;
2240
+ decodeResult.decoder.decodeLevel = "none";
2554
2241
  }
2555
- decodeResult.decoded = true;
2556
- decodeResult.decoder.decodeLevel = "partial";
2557
2242
  return decodeResult;
2558
2243
  }
2559
2244
  };
2245
+ function processPosition(decodeResult, value) {
2246
+ if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
2247
+ return;
2248
+ }
2249
+ const latDir = value[0] === "N" ? 1 : -1;
2250
+ const lonDir = value[8] === "E" ? 1 : -1;
2251
+ const position = {
2252
+ latitude: latDir * Number(value.substring(1, 7)),
2253
+ longitude: lonDir * Number(value.substring(9, 15))
2254
+ };
2255
+ ResultFormatter.position(decodeResult, position);
2256
+ }
2560
2257
 
2561
- // lib/plugins/Label_1L_3-line.ts
2562
- var Label_1L_3Line = class extends DecoderPlugin {
2563
- name = "label-1l-3-line";
2258
+ // lib/plugins/Label_22_OFF.ts
2259
+ var Label_22_OFF = class extends DecoderPlugin {
2260
+ name = "label-22-off";
2564
2261
  qualifiers() {
2565
2262
  return {
2566
- labels: ["1L"]
2263
+ labels: ["22"],
2264
+ preambles: ["OFF"]
2567
2265
  };
2568
2266
  }
2569
2267
  decode(message, options = {}) {
2570
2268
  const decodeResult = this.defaultResult();
2571
2269
  decodeResult.decoder.name = this.name;
2572
- decodeResult.formatted.description = "Position Report";
2270
+ decodeResult.formatted.description = "Takeoff Report";
2573
2271
  decodeResult.message = message;
2574
- const lines = message.text.split("\r\n");
2575
- if (lines.length !== 3) {
2272
+ if (message.text.startsWith("OFF01")) {
2273
+ const fields = message.text.substring(5).split("/");
2274
+ if (fields.length != 2) {
2275
+ decodeResult.decoded = false;
2276
+ decodeResult.decoder.decodeLevel = "none";
2277
+ return decodeResult;
2278
+ }
2279
+ ResultFormatter.flightNumber(decodeResult, fields[0]);
2280
+ ResultFormatter.departureDay(
2281
+ decodeResult,
2282
+ Number(fields[1].substring(0, 2))
2283
+ );
2284
+ ResultFormatter.arrivalDay(
2285
+ decodeResult,
2286
+ Number(fields[1].substring(2, 4))
2287
+ );
2288
+ ResultFormatter.time_of_day(
2289
+ decodeResult,
2290
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8))
2291
+ );
2292
+ ResultFormatter.departureAirport(
2293
+ decodeResult,
2294
+ fields[1].substring(8, 12)
2295
+ );
2296
+ ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
2297
+ ResultFormatter.off(
2298
+ decodeResult,
2299
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22))
2300
+ );
2301
+ ResultFormatter.unknown(decodeResult, fields[1].substring(22));
2302
+ decodeResult.decoded = true;
2303
+ decodeResult.decoder.decodeLevel = "partial";
2304
+ } else if (message.text.startsWith("OFF02\r\n")) {
2305
+ const fields = message.text.substring(7).split(",");
2306
+ if (fields.length != 4) {
2307
+ decodeResult.decoded = false;
2308
+ decodeResult.decoder.decodeLevel = "none";
2309
+ return decodeResult;
2310
+ }
2311
+ ResultFormatter.departureAirport(decodeResult, fields[0]);
2312
+ ResultFormatter.arrivalAirport(decodeResult, fields[1]);
2313
+ ResultFormatter.off(
2314
+ decodeResult,
2315
+ DateTimeUtils.convertHHMMSSToTod(fields[2])
2316
+ );
2317
+ ResultFormatter.unknown(decodeResult, fields[3]);
2318
+ decodeResult.decoded = true;
2319
+ decodeResult.decoder.decodeLevel = "partial";
2320
+ } else if (message.text.startsWith("OFF02")) {
2321
+ const fields = message.text.substring(5).split("/");
2322
+ if (fields.length != 2) {
2323
+ decodeResult.decoded = false;
2324
+ decodeResult.decoder.decodeLevel = "none";
2325
+ return decodeResult;
2326
+ }
2327
+ ResultFormatter.flightNumber(decodeResult, fields[0]);
2328
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2329
+ fields[1].substring(0, 14)
2330
+ );
2331
+ if (position) {
2332
+ ResultFormatter.position(decodeResult, position);
2333
+ }
2334
+ ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
2335
+ ResultFormatter.time_of_day(
2336
+ decodeResult,
2337
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20))
2338
+ );
2339
+ ResultFormatter.departureAirport(
2340
+ decodeResult,
2341
+ fields[1].substring(20, 24)
2342
+ );
2343
+ ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
2344
+ ResultFormatter.off(
2345
+ decodeResult,
2346
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32))
2347
+ );
2348
+ ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
2349
+ ResultFormatter.eta(
2350
+ decodeResult,
2351
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40))
2352
+ );
2353
+ decodeResult.decoded = true;
2354
+ decodeResult.decoder.decodeLevel = "partial";
2355
+ } else {
2576
2356
  if (options.debug) {
2577
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2357
+ console.log(`DEBUG: ${this.name}: Unknown variation.`);
2578
2358
  }
2579
- decodeResult.remaining.text = message.text;
2580
2359
  decodeResult.decoded = false;
2581
2360
  decodeResult.decoder.decodeLevel = "none";
2582
- return decodeResult;
2583
- }
2584
- const parts = message.text.replaceAll("\r\n", "/").split("/");
2585
- const data = /* @__PURE__ */ new Map();
2586
- data.set("", parts[0]);
2587
- for (let i = 1; i < parts.length; i++) {
2588
- const part = parts[i].split(" ");
2589
- data.set(part[0], part.slice(1).join(" "));
2590
- }
2591
- const dep = data.get("DEP");
2592
- if (dep) {
2593
- ResultFormatter.departureAirport(decodeResult, dep);
2594
- data.delete("DEP");
2595
- }
2596
- const des = data.get("DES");
2597
- if (des) {
2598
- ResultFormatter.arrivalAirport(decodeResult, des);
2599
- data.delete("DES");
2600
- }
2601
- const eta = data.get("ETA");
2602
- if (eta) {
2603
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
2604
- data.delete("ETA");
2605
- }
2606
- const alt = data.get("ALT");
2607
- if (alt) {
2608
- ResultFormatter.altitude(decodeResult, Number(alt));
2609
- data.delete("ALT");
2610
- }
2611
- const fn = data.get("FN");
2612
- if (fn) {
2613
- ResultFormatter.flightNumber(decodeResult, fn);
2614
- data.delete("FN");
2615
- }
2616
- const day = data.get("DAY");
2617
- const utc = data.get("UTC");
2618
- if (day && utc) {
2619
- decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
2620
- data.delete("DAY");
2621
- data.delete("UTC");
2622
- }
2623
- const lat = data.get("LAT");
2624
- const lon = data.get("LON");
2625
- if (lat && lon) {
2626
- ResultFormatter.position(decodeResult, {
2627
- latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
2628
- longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
2629
- });
2630
- data.delete("LAT");
2631
- data.delete("LON");
2632
- }
2633
- let remaining = "";
2634
- for (const [key, value] of data.entries()) {
2635
- if (key === "") {
2636
- remaining += value;
2637
- } else {
2638
- remaining += `/${key} ${value}`;
2639
- }
2640
2361
  }
2641
- decodeResult.remaining.text = remaining;
2642
- decodeResult.decoded = true;
2643
- decodeResult.decoder.decodeLevel = "partial";
2644
2362
  return decodeResult;
2645
2363
  }
2646
2364
  };
2647
2365
 
2648
- // lib/plugins/Label_1L_070.ts
2649
- var Label_1L_070 = class extends DecoderPlugin {
2650
- name = "label-1l-070";
2366
+ // lib/plugins/Label_22_POS.ts
2367
+ var Label_22_POS = class extends DecoderPlugin {
2368
+ name = "label-22-pos";
2651
2369
  qualifiers() {
2652
2370
  return {
2653
- labels: ["1L"],
2654
- preambles: ["000000070"]
2371
+ labels: ["22"],
2372
+ preambles: ["N", "S"]
2655
2373
  };
2656
2374
  }
2657
2375
  decode(message, options = {}) {
@@ -2659,217 +2377,216 @@ var Label_1L_070 = class extends DecoderPlugin {
2659
2377
  decodeResult.decoder.name = this.name;
2660
2378
  decodeResult.formatted.description = "Position Report";
2661
2379
  decodeResult.message = message;
2662
- if (!message.text.startsWith("000000070")) {
2663
- if (options.debug) {
2664
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2665
- }
2666
- decodeResult.remaining.text = message.text;
2667
- decodeResult.decoded = false;
2668
- decodeResult.decoder.decodeLevel = "none";
2669
- return decodeResult;
2670
- }
2671
- const parts = message.text.substring(9).split(",");
2672
- if (parts.length !== 7) {
2380
+ const fields = message.text.split(",");
2381
+ if (fields.length !== 11) {
2673
2382
  if (options.debug) {
2674
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2383
+ console.log(
2384
+ `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`
2385
+ );
2675
2386
  }
2676
- decodeResult.remaining.text = message.text;
2677
2387
  decodeResult.decoded = false;
2678
2388
  decodeResult.decoder.decodeLevel = "none";
2679
2389
  return decodeResult;
2680
2390
  }
2681
- ResultFormatter.departureAirport(decodeResult, parts[0]);
2682
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2391
+ const latStr = fields[0].substring(1, 8);
2392
+ const lonStr = fields[0].substring(9);
2393
+ const lat = Number(latStr) / 1e4;
2394
+ const lon = Number(lonStr) / 1e4;
2395
+ ResultFormatter.position(decodeResult, {
2396
+ latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
2397
+ longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
2398
+ });
2683
2399
  ResultFormatter.time_of_day(
2684
2400
  decodeResult,
2685
- DateTimeUtils.convertHHMMSSToTod(parts[2])
2686
- );
2687
- ResultFormatter.eta(
2688
- decodeResult,
2689
- DateTimeUtils.convertHHMMSSToTod(parts[3])
2401
+ DateTimeUtils.convertHHMMSSToTod(fields[2])
2690
2402
  );
2691
- ResultFormatter.position(decodeResult, {
2692
- latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
2693
- longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
2694
- });
2695
- decodeResult.remaining.text = parts[6];
2403
+ ResultFormatter.altitude(decodeResult, Number(fields[3]));
2404
+ ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
2696
2405
  decodeResult.decoded = true;
2697
2406
  decodeResult.decoder.decodeLevel = "partial";
2698
2407
  return decodeResult;
2699
2408
  }
2700
2409
  };
2701
2410
 
2702
- // lib/plugins/Label_1L_660.ts
2703
- var Label_1L_660 = class extends DecoderPlugin {
2704
- name = "label-1l-660";
2411
+ // lib/plugins/Label_2P_FM3.ts
2412
+ var Label_2P_FM3 = class extends DecoderPlugin {
2413
+ name = "label-2p-fm3";
2705
2414
  qualifiers() {
2706
2415
  return {
2707
- labels: ["1L"],
2708
- preambles: ["000000660"]
2416
+ labels: ["2P"]
2709
2417
  };
2710
2418
  }
2711
2419
  decode(message, options = {}) {
2712
- const decodeResult = this.defaultResult();
2420
+ let decodeResult = this.defaultResult();
2713
2421
  decodeResult.decoder.name = this.name;
2714
- decodeResult.formatted.description = "Position Report";
2422
+ decodeResult.formatted.description = "Flight Report";
2715
2423
  decodeResult.message = message;
2716
- if (!message.text.startsWith("000000660")) {
2717
- if (options.debug) {
2718
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2424
+ const parts = message.text.split(",");
2425
+ if (parts.length === 7) {
2426
+ const header = parts[0].split("FM3 ");
2427
+ if (header.length == 0) {
2428
+ ResultFormatter.unknown(decodeResult, message.text);
2429
+ decodeResult.decoded = false;
2430
+ decodeResult.decoder.decodeLevel = "none";
2431
+ return decodeResult;
2719
2432
  }
2720
- decodeResult.remaining.text = message.text;
2721
- decodeResult.decoded = false;
2722
- decodeResult.decoder.decodeLevel = "none";
2723
- return decodeResult;
2724
- }
2725
- const parts = message.text.substring(9).split(",");
2726
- if (parts.length !== 5) {
2727
- if (options.debug) {
2728
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2433
+ if (header[0].length > 0) {
2434
+ ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
2435
+ ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2729
2436
  }
2730
- decodeResult.remaining.text = message.text;
2731
- decodeResult.decoded = false;
2732
- decodeResult.decoder.decodeLevel = "none";
2733
- return decodeResult;
2734
- }
2735
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2736
- parts[0]
2737
- );
2738
- if (position) {
2739
- ResultFormatter.position(decodeResult, position);
2740
- }
2741
- const hhmmss = parts[1].substring(0, 6);
2742
- ResultFormatter.time_of_day(
2743
- decodeResult,
2744
- DateTimeUtils.convertHHMMSSToTod(hhmmss)
2745
- );
2746
- const fl = parts[1].substring(6, 9);
2747
- ResultFormatter.altitude(decodeResult, Number(fl) * 100);
2748
- const next = parts[1].substring(9);
2749
- ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
2750
- decodeResult.remaining.text = parts.slice(2).join(",");
2751
- decodeResult.decoded = true;
2752
- decodeResult.decoder.decodeLevel = "partial";
2437
+ if (header[1].length === 4) {
2438
+ ResultFormatter.time_of_day(
2439
+ decodeResult,
2440
+ DateTimeUtils.convertHHMMSSToTod(header[1])
2441
+ );
2442
+ } else {
2443
+ ResultFormatter.time_of_day(
2444
+ decodeResult,
2445
+ DateTimeUtils.convertHHMMSSToTod(header[1])
2446
+ );
2447
+ }
2448
+ ResultFormatter.eta(
2449
+ decodeResult,
2450
+ DateTimeUtils.convertHHMMSSToTod(parts[1])
2451
+ );
2452
+ const lat = parts[2].replaceAll(" ", "");
2453
+ const lon = parts[3].replaceAll(" ", "");
2454
+ if (lat[0] === "N" || lat[0] === "S") {
2455
+ ResultFormatter.position(decodeResult, {
2456
+ latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
2457
+ longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
2458
+ });
2459
+ } else {
2460
+ ResultFormatter.position(decodeResult, {
2461
+ latitude: Number(lat),
2462
+ longitude: Number(lon)
2463
+ });
2464
+ }
2465
+ ResultFormatter.altitude(decodeResult, Number(parts[4]));
2466
+ ResultFormatter.unknown(decodeResult, parts[5]);
2467
+ ResultFormatter.unknown(decodeResult, parts[6]);
2468
+ decodeResult.decoded = true;
2469
+ decodeResult.decoder.decodeLevel = "partial";
2470
+ } else {
2471
+ if (options.debug) {
2472
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2473
+ }
2474
+ ResultFormatter.unknown(decodeResult, message.text);
2475
+ decodeResult.decoded = false;
2476
+ decodeResult.decoder.decodeLevel = "none";
2477
+ }
2753
2478
  return decodeResult;
2754
2479
  }
2755
2480
  };
2756
2481
 
2757
- // lib/plugins/Label_1L_Slash.ts
2758
- var Label_1L_Slash = class extends DecoderPlugin {
2759
- name = "label-1l-1-line";
2482
+ // lib/plugins/Label_2P_FM4.ts
2483
+ var Label_2P_FM4 = class extends DecoderPlugin {
2484
+ name = "label-2p-fm4";
2760
2485
  qualifiers() {
2761
2486
  return {
2762
- labels: ["1L"],
2763
- preambles: ["+", "-"]
2487
+ labels: ["2P"]
2764
2488
  };
2765
2489
  }
2766
2490
  decode(message, options = {}) {
2767
- const decodeResult = this.defaultResult();
2491
+ let decodeResult = this.defaultResult();
2768
2492
  decodeResult.decoder.name = this.name;
2769
- decodeResult.formatted.description = "Position Report";
2493
+ decodeResult.formatted.description = "Flight Report";
2770
2494
  decodeResult.message = message;
2771
- const parts = message.text.split("/");
2772
- if (parts.length !== 7) {
2773
- if (options.debug) {
2774
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
2495
+ const parts = message.text.split(",");
2496
+ if (parts.length === 10) {
2497
+ const header = parts[0].split("FM4");
2498
+ if (header.length == 0) {
2499
+ ResultFormatter.unknown(decodeResult, message.text);
2500
+ decodeResult.decoded = false;
2501
+ decodeResult.decoder.decodeLevel = "none";
2502
+ return decodeResult;
2775
2503
  }
2776
- decodeResult.remaining.text = message.text;
2777
- decodeResult.decoded = false;
2778
- decodeResult.decoder.decodeLevel = "none";
2779
- return decodeResult;
2780
- }
2781
- const data = /* @__PURE__ */ new Map();
2782
- data.set("LAT", parts[0].replaceAll(" ", ""));
2783
- data.set("LON", parts[1].replaceAll(" ", ""));
2784
- for (let i = 2; i < parts.length; i++) {
2785
- const part = parts[i].split(" ");
2786
- data.set(part[0], part.slice(1).join(" "));
2787
- }
2788
- const position = {
2789
- latitude: Number(data.get("LAT")),
2790
- longitude: Number(data.get("LON"))
2791
- };
2792
- data.delete("LAT");
2793
- data.delete("LON");
2794
- ResultFormatter.position(decodeResult, position);
2795
- const utc = data.get("UTC");
2796
- if (utc) {
2504
+ if (header[0].length > 0) {
2505
+ ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
2506
+ ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2507
+ }
2508
+ ResultFormatter.departureAirport(decodeResult, header[1]);
2509
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2510
+ ResultFormatter.day(decodeResult, Number(parts[2].substring(0, 2)));
2797
2511
  ResultFormatter.time_of_day(
2798
2512
  decodeResult,
2799
- DateTimeUtils.convertHHMMSSToTod(utc)
2513
+ DateTimeUtils.convertHHMMSSToTod(parts[2].substring(2))
2800
2514
  );
2801
- data.delete("UTC");
2802
- }
2803
- const alt = data.get("ALT");
2804
- if (alt) {
2805
- ResultFormatter.altitude(decodeResult, Number(alt));
2806
- data.delete("ALT");
2807
- }
2808
- const fob = data.get("FOB");
2809
- if (fob) {
2810
- ResultFormatter.currentFuel(decodeResult, Number(fob));
2811
- data.delete("FOB");
2812
- }
2813
- const eta = data.get("ETA");
2814
- if (eta) {
2815
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
2816
- data.delete("ETA");
2817
- }
2818
- let remaining = "";
2819
- for (const [key, value] of data.entries()) {
2820
- remaining += `/${key} ${value}`;
2515
+ ResultFormatter.eta(
2516
+ decodeResult,
2517
+ DateTimeUtils.convertHHMMSSToTod(parts[3])
2518
+ );
2519
+ ResultFormatter.position(decodeResult, {
2520
+ latitude: Number(parts[4].replaceAll(" ", "")),
2521
+ longitude: Number(parts[5].replaceAll(" ", ""))
2522
+ });
2523
+ ResultFormatter.altitude(decodeResult, Number(parts[6]));
2524
+ ResultFormatter.heading(decodeResult, Number(parts[7]));
2525
+ ResultFormatter.unknown(decodeResult, parts[8]);
2526
+ ResultFormatter.unknown(decodeResult, parts[9]);
2527
+ decodeResult.decoded = true;
2528
+ decodeResult.decoder.decodeLevel = "partial";
2529
+ } else {
2530
+ if (options.debug) {
2531
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2532
+ }
2533
+ ResultFormatter.unknown(decodeResult, message.text);
2534
+ decodeResult.decoded = false;
2535
+ decodeResult.decoder.decodeLevel = "none";
2821
2536
  }
2822
- decodeResult.remaining.text = remaining;
2823
- decodeResult.decoded = true;
2824
- decodeResult.decoder.decodeLevel = "partial";
2825
2537
  return decodeResult;
2826
2538
  }
2827
2539
  };
2828
2540
 
2829
- // lib/plugins/Label_20_POS.ts
2830
- var Label_20_POS = class extends DecoderPlugin {
2831
- name = "label-20-pos";
2541
+ // lib/plugins/Label_2P_FM5.ts
2542
+ var Label_2P_FM5 = class extends DecoderPlugin {
2543
+ name = "label-2p-fm5";
2832
2544
  qualifiers() {
2833
2545
  return {
2834
- labels: ["20"],
2835
- preambles: ["POS"]
2546
+ labels: ["2P"]
2836
2547
  };
2837
2548
  }
2838
2549
  decode(message, options = {}) {
2839
- const decodeResult = this.defaultResult();
2550
+ let decodeResult = this.defaultResult();
2840
2551
  decodeResult.decoder.name = this.name;
2841
- decodeResult.formatted.description = "Position Report";
2552
+ decodeResult.formatted.description = "Flight Report";
2842
2553
  decodeResult.message = message;
2843
- decodeResult.raw.preamble = message.text.substring(0, 3);
2844
- const content = message.text.substring(3);
2845
- const fields = content.split(",");
2846
- if (fields.length == 11) {
2847
- if (options.debug) {
2848
- console.log(`DEBUG: ${this.name}: Variation 1 detected`);
2554
+ const parts = message.text.split(",");
2555
+ if (parts.length === 12) {
2556
+ const header = parts[0].split("FM5 ");
2557
+ if (header.length == 0) {
2558
+ ResultFormatter.unknown(decodeResult, message.text);
2559
+ decodeResult.decoded = false;
2560
+ decodeResult.decoder.decodeLevel = "none";
2561
+ return decodeResult;
2849
2562
  }
2850
- const rawCoords = fields[0];
2851
- ResultFormatter.position(
2563
+ ResultFormatter.departureAirport(decodeResult, header[1]);
2564
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2565
+ ResultFormatter.time_of_day(
2852
2566
  decodeResult,
2853
- CoordinateUtils.decodeStringCoordinates(rawCoords)
2567
+ DateTimeUtils.convertHHMMSSToTod(parts[2])
2854
2568
  );
2569
+ ResultFormatter.eta(
2570
+ decodeResult,
2571
+ DateTimeUtils.convertHHMMSSToTod(parts[3])
2572
+ );
2573
+ ResultFormatter.position(decodeResult, {
2574
+ latitude: Number(parts[4].replaceAll(" ", "")),
2575
+ longitude: Number(parts[5].replaceAll(" ", ""))
2576
+ });
2577
+ ResultFormatter.altitude(decodeResult, Number(parts[6]));
2578
+ ResultFormatter.unknown(decodeResult, parts[7]);
2579
+ ResultFormatter.unknown(decodeResult, parts[8]);
2580
+ ResultFormatter.unknown(decodeResult, parts[9]);
2581
+ ResultFormatter.flightNumber(decodeResult, parts[10].trim());
2582
+ ResultFormatter.unknown(decodeResult, parts[11]);
2855
2583
  decodeResult.decoded = true;
2856
- decodeResult.decoder.decodeLevel = "full";
2857
- } else if (fields.length == 5) {
2858
- if (options.debug) {
2859
- console.log(`DEBUG: ${this.name}: Variation 2 detected`);
2860
- }
2861
- const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
2862
- if (position) {
2863
- ResultFormatter.position(decodeResult, position);
2864
- }
2865
- decodeResult.decoded = true;
2866
- decodeResult.decoder.decodeLevel = "full";
2584
+ decodeResult.decoder.decodeLevel = "partial";
2867
2585
  } else {
2868
2586
  if (options.debug) {
2869
- console.log(
2870
- `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`
2871
- );
2587
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2872
2588
  }
2589
+ ResultFormatter.unknown(decodeResult, message.text);
2873
2590
  decodeResult.decoded = false;
2874
2591
  decodeResult.decoder.decodeLevel = "none";
2875
2592
  }
@@ -2877,13 +2594,13 @@ var Label_20_POS = class extends DecoderPlugin {
2877
2594
  }
2878
2595
  };
2879
2596
 
2880
- // lib/plugins/Label_21_POS.ts
2881
- var Label_21_POS = class extends DecoderPlugin {
2882
- name = "label-21-pos";
2597
+ // lib/plugins/Label_24_Slash.ts
2598
+ var Label_24_Slash = class extends DecoderPlugin {
2599
+ name = "label-24-slash";
2883
2600
  qualifiers() {
2884
2601
  return {
2885
- labels: ["21"],
2886
- preambles: ["POS"]
2602
+ labels: ["24"],
2603
+ preambles: ["/"]
2887
2604
  };
2888
2605
  }
2889
2606
  decode(message, options = {}) {
@@ -2891,33 +2608,34 @@ var Label_21_POS = class extends DecoderPlugin {
2891
2608
  decodeResult.decoder.name = this.name;
2892
2609
  decodeResult.formatted.description = "Position Report";
2893
2610
  decodeResult.message = message;
2894
- decodeResult.raw.preamble = message.text.substring(0, 3);
2895
- const content = message.text.substring(3);
2896
- const fields = content.split(",");
2897
- if (fields.length == 9) {
2898
- processPosition(decodeResult, fields[0].trim());
2899
- ResultFormatter.time_of_day(
2900
- decodeResult,
2901
- DateTimeUtils.convertHHMMSSToTod(fields[2])
2611
+ const fields = message.text.split("/");
2612
+ if (fields.length == 10 && fields[0] == "" && fields[9] == "") {
2613
+ const ddmmyy = fields[1].substring(2, 4) + fields[1].substring(4, 6) + fields[1].substring(0, 2);
2614
+ const hhmmss = fields[2] + "00";
2615
+ decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(
2616
+ hhmmss,
2617
+ ddmmyy
2902
2618
  );
2903
- ResultFormatter.altitude(decodeResult, Number(fields[3]));
2904
- ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
2619
+ ResultFormatter.flightNumber(decodeResult, fields[3]);
2620
+ ResultFormatter.altitude(decodeResult, Number(fields[4]));
2621
+ const lat = fields[5];
2622
+ const lon = fields[6];
2623
+ const position = {
2624
+ latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
2625
+ longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
2626
+ };
2627
+ ResultFormatter.position(decodeResult, position);
2905
2628
  ResultFormatter.eta(
2906
2629
  decodeResult,
2907
- DateTimeUtils.convertHHMMSSToTod(fields[7])
2630
+ DateTimeUtils.convertHHMMSSToTod(fields[8])
2908
2631
  );
2909
- ResultFormatter.arrivalAirport(decodeResult, fields[8]);
2910
- ResultFormatter.unknownArr(decodeResult, [
2911
- fields[1],
2912
- fields[4],
2913
- fields[5]
2914
- ]);
2632
+ ResultFormatter.unknown(decodeResult, fields[7]);
2915
2633
  decodeResult.decoded = true;
2916
2634
  decodeResult.decoder.decodeLevel = "partial";
2917
2635
  } else {
2918
2636
  if (options.debug) {
2919
2637
  console.log(
2920
- `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`
2638
+ `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`
2921
2639
  );
2922
2640
  }
2923
2641
  decodeResult.decoded = false;
@@ -2926,480 +2644,565 @@ var Label_21_POS = class extends DecoderPlugin {
2926
2644
  return decodeResult;
2927
2645
  }
2928
2646
  };
2929
- function processPosition(decodeResult, value) {
2930
- if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
2931
- return;
2932
- }
2933
- const latDir = value[0] === "N" ? 1 : -1;
2934
- const lonDir = value[8] === "E" ? 1 : -1;
2935
- const position = {
2936
- latitude: latDir * Number(value.substring(1, 7)),
2937
- longitude: lonDir * Number(value.substring(9, 15))
2938
- };
2939
- ResultFormatter.position(decodeResult, position);
2940
- }
2941
2647
 
2942
- // lib/plugins/Label_22_OFF.ts
2943
- var Label_22_OFF = class extends DecoderPlugin {
2944
- name = "label-22-off";
2648
+ // lib/plugins/Label_30_Slash_EA.ts
2649
+ var Label_30_Slash_EA = class extends DecoderPlugin {
2650
+ name = "label-30-slash-ea";
2945
2651
  qualifiers() {
2946
2652
  return {
2947
- labels: ["22"],
2948
- preambles: ["OFF"]
2653
+ labels: ["30"],
2654
+ preambles: ["/EA"]
2949
2655
  };
2950
2656
  }
2951
2657
  decode(message, options = {}) {
2952
2658
  const decodeResult = this.defaultResult();
2953
2659
  decodeResult.decoder.name = this.name;
2954
- decodeResult.formatted.description = "Takeoff Report";
2660
+ decodeResult.formatted.description = "ETA Report";
2955
2661
  decodeResult.message = message;
2956
- if (message.text.startsWith("OFF01")) {
2957
- const fields = message.text.substring(5).split("/");
2958
- if (fields.length != 2) {
2959
- decodeResult.decoded = false;
2960
- decodeResult.decoder.decodeLevel = "none";
2961
- return decodeResult;
2662
+ const results = message.text.split(/\n|\//).slice(1);
2663
+ if (results) {
2664
+ if (options.debug) {
2665
+ console.log("Label 30 EA: results");
2666
+ console.log(results);
2962
2667
  }
2963
- ResultFormatter.flightNumber(decodeResult, fields[0]);
2964
- ResultFormatter.departureDay(
2965
- decodeResult,
2966
- Number(fields[1].substring(0, 2))
2967
- );
2968
- ResultFormatter.arrivalDay(
2969
- decodeResult,
2970
- Number(fields[1].substring(2, 4))
2971
- );
2972
- ResultFormatter.time_of_day(
2973
- decodeResult,
2974
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8))
2975
- );
2976
- ResultFormatter.departureAirport(
2977
- decodeResult,
2978
- fields[1].substring(8, 12)
2979
- );
2980
- ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
2981
- ResultFormatter.off(
2668
+ }
2669
+ ResultFormatter.eta(
2670
+ decodeResult,
2671
+ DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4))
2672
+ );
2673
+ if (results[1].substring(0, 2) === "DS") {
2674
+ ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6));
2675
+ ResultFormatter.unknown(decodeResult, "/".concat(results[2]));
2676
+ } else {
2677
+ ResultFormatter.unknown(
2982
2678
  decodeResult,
2983
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22))
2679
+ "/".concat(results[1], "/", results[2])
2984
2680
  );
2985
- ResultFormatter.unknown(decodeResult, fields[1].substring(22));
2986
- decodeResult.decoded = true;
2987
- decodeResult.decoder.decodeLevel = "partial";
2988
- } else if (message.text.startsWith("OFF02\r\n")) {
2989
- const fields = message.text.substring(7).split(",");
2990
- if (fields.length != 4) {
2991
- decodeResult.decoded = false;
2992
- decodeResult.decoder.decodeLevel = "none";
2993
- return decodeResult;
2681
+ }
2682
+ decodeResult.decoded = true;
2683
+ decodeResult.decoder.decodeLevel = "partial";
2684
+ return decodeResult;
2685
+ }
2686
+ };
2687
+
2688
+ // lib/plugins/Label_44_ETA.ts
2689
+ var Label_44_ETA = class extends DecoderPlugin {
2690
+ name = "label-44-eta";
2691
+ qualifiers() {
2692
+ return {
2693
+ labels: ["44"],
2694
+ preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
2695
+ };
2696
+ }
2697
+ decode(message, options = {}) {
2698
+ const decodeResult = this.defaultResult();
2699
+ decodeResult.decoder.name = this.name;
2700
+ decodeResult.formatted.description = "ETA Report";
2701
+ decodeResult.message = message;
2702
+ const data = message.text.split(",");
2703
+ if (data.length >= 9) {
2704
+ if (options.debug) {
2705
+ console.log("Label 44 ETA Report: groups");
2706
+ console.log(data);
2994
2707
  }
2995
- ResultFormatter.departureAirport(decodeResult, fields[0]);
2996
- ResultFormatter.arrivalAirport(decodeResult, fields[1]);
2997
- ResultFormatter.off(
2708
+ ResultFormatter.position(
2998
2709
  decodeResult,
2999
- DateTimeUtils.convertHHMMSSToTod(fields[2])
3000
- );
3001
- ResultFormatter.unknown(decodeResult, fields[3]);
3002
- decodeResult.decoded = true;
3003
- decodeResult.decoder.decodeLevel = "partial";
3004
- } else if (message.text.startsWith("OFF02")) {
3005
- const fields = message.text.substring(5).split("/");
3006
- if (fields.length != 2) {
3007
- decodeResult.decoded = false;
3008
- decodeResult.decoder.decodeLevel = "none";
3009
- return decodeResult;
3010
- }
3011
- ResultFormatter.flightNumber(decodeResult, fields[0]);
3012
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
3013
- fields[1].substring(0, 14)
2710
+ CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3014
2711
  );
3015
- if (position) {
3016
- ResultFormatter.position(decodeResult, position);
3017
- }
3018
- ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
2712
+ ResultFormatter.altitude(decodeResult, 100 * Number(data[2]));
2713
+ ResultFormatter.departureAirport(decodeResult, data[3]);
2714
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
2715
+ ResultFormatter.month(decodeResult, Number(data[5].substring(0, 2)));
2716
+ ResultFormatter.day(decodeResult, Number(data[5].substring(2, 4)));
3019
2717
  ResultFormatter.time_of_day(
3020
2718
  decodeResult,
3021
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20))
3022
- );
3023
- ResultFormatter.departureAirport(
3024
- decodeResult,
3025
- fields[1].substring(20, 24)
3026
- );
3027
- ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
3028
- ResultFormatter.off(
3029
- decodeResult,
3030
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32))
2719
+ DateTimeUtils.convertHHMMSSToTod(data[6])
3031
2720
  );
3032
- ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
3033
2721
  ResultFormatter.eta(
3034
2722
  decodeResult,
3035
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40))
2723
+ DateTimeUtils.convertHHMMSSToTod(data[7])
3036
2724
  );
3037
- decodeResult.decoded = true;
3038
- decodeResult.decoder.decodeLevel = "partial";
2725
+ const fuel = Number(data[8]);
2726
+ if (!isNaN(fuel)) {
2727
+ ResultFormatter.remainingFuel(decodeResult, Number(fuel));
2728
+ }
2729
+ if (data.length > 9) {
2730
+ ResultFormatter.unknownArr(decodeResult, data.slice(9));
2731
+ }
3039
2732
  } else {
3040
2733
  if (options.debug) {
3041
- console.log(`DEBUG: ${this.name}: Unknown variation.`);
2734
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3042
2735
  }
2736
+ ResultFormatter.unknown(decodeResult, message.text);
3043
2737
  decodeResult.decoded = false;
3044
2738
  decodeResult.decoder.decodeLevel = "none";
2739
+ return decodeResult;
3045
2740
  }
2741
+ decodeResult.decoded = true;
2742
+ decodeResult.decoder.decodeLevel = "full";
3046
2743
  return decodeResult;
3047
2744
  }
3048
2745
  };
3049
2746
 
3050
- // lib/plugins/Label_22_POS.ts
3051
- var Label_22_POS = class extends DecoderPlugin {
3052
- name = "label-22-pos";
2747
+ // lib/plugins/Label_44_IN.ts
2748
+ var Label_44_IN = class extends DecoderPlugin {
2749
+ name = "label-44-in";
3053
2750
  qualifiers() {
3054
2751
  return {
3055
- labels: ["22"],
3056
- preambles: ["N", "S"]
2752
+ labels: ["44"],
2753
+ preambles: ["00IN01", "00IN02", "00IN03", "IN01", "IN02", "IN03"]
3057
2754
  };
3058
2755
  }
3059
2756
  decode(message, options = {}) {
3060
2757
  const decodeResult = this.defaultResult();
3061
2758
  decodeResult.decoder.name = this.name;
3062
- decodeResult.formatted.description = "Position Report";
2759
+ decodeResult.formatted.description = "In Air Report";
3063
2760
  decodeResult.message = message;
3064
- const fields = message.text.split(",");
3065
- if (fields.length !== 11) {
2761
+ const data = message.text.split(",");
2762
+ if (data.length >= 7) {
3066
2763
  if (options.debug) {
3067
- console.log(
3068
- `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`
3069
- );
2764
+ console.log("Label 44 In Air Report: groups");
2765
+ console.log(data);
2766
+ }
2767
+ ResultFormatter.position(
2768
+ decodeResult,
2769
+ CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
2770
+ );
2771
+ ResultFormatter.departureAirport(decodeResult, data[2]);
2772
+ ResultFormatter.arrivalAirport(decodeResult, data[3]);
2773
+ ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
2774
+ ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
2775
+ ResultFormatter.in(
2776
+ decodeResult,
2777
+ DateTimeUtils.convertHHMMSSToTod(data[5])
2778
+ );
2779
+ const fuel = Number(data[6]);
2780
+ if (!isNaN(fuel)) {
2781
+ ResultFormatter.remainingFuel(decodeResult, Number(fuel));
2782
+ }
2783
+ if (data.length > 7) {
2784
+ ResultFormatter.unknownArr(decodeResult, data.slice(7));
2785
+ }
2786
+ } else {
2787
+ if (options.debug) {
2788
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3070
2789
  }
2790
+ ResultFormatter.unknown(decodeResult, message.text);
3071
2791
  decodeResult.decoded = false;
3072
2792
  decodeResult.decoder.decodeLevel = "none";
3073
2793
  return decodeResult;
3074
2794
  }
3075
- const latStr = fields[0].substring(1, 8);
3076
- const lonStr = fields[0].substring(9);
3077
- const lat = Number(latStr) / 1e4;
3078
- const lon = Number(lonStr) / 1e4;
3079
- ResultFormatter.position(decodeResult, {
3080
- latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
3081
- longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
3082
- });
3083
- ResultFormatter.time_of_day(
3084
- decodeResult,
3085
- DateTimeUtils.convertHHMMSSToTod(fields[2])
3086
- );
3087
- ResultFormatter.altitude(decodeResult, Number(fields[3]));
3088
- ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
3089
2795
  decodeResult.decoded = true;
3090
- decodeResult.decoder.decodeLevel = "partial";
2796
+ decodeResult.decoder.decodeLevel = "full";
3091
2797
  return decodeResult;
3092
2798
  }
3093
2799
  };
3094
2800
 
3095
- // lib/plugins/Label_2P_FM3.ts
3096
- var Label_2P_FM3 = class extends DecoderPlugin {
3097
- name = "label-2p-fm3";
2801
+ // lib/plugins/Label_44_OFF.ts
2802
+ var Label_44_OFF = class extends DecoderPlugin {
2803
+ name = "label-44-off";
3098
2804
  qualifiers() {
3099
2805
  return {
3100
- labels: ["2P"]
2806
+ labels: ["44"],
2807
+ preambles: ["00OFF01", "00OFF02", "00OFF03", "OFF01", "OFF02", "OFF03"]
3101
2808
  };
3102
2809
  }
3103
2810
  decode(message, options = {}) {
3104
- let decodeResult = this.defaultResult();
2811
+ const decodeResult = this.defaultResult();
3105
2812
  decodeResult.decoder.name = this.name;
3106
- decodeResult.formatted.description = "Flight Report";
2813
+ decodeResult.formatted.description = "Off Runway Report";
3107
2814
  decodeResult.message = message;
3108
- const parts = message.text.split(",");
3109
- if (parts.length === 7) {
3110
- const header = parts[0].split("FM3 ");
3111
- if (header.length == 0) {
3112
- ResultFormatter.unknown(decodeResult, message.text);
3113
- decodeResult.decoded = false;
3114
- decodeResult.decoder.decodeLevel = "none";
3115
- return decodeResult;
3116
- }
3117
- if (header[0].length > 0) {
3118
- ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
3119
- ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
3120
- }
3121
- if (header[1].length === 4) {
3122
- ResultFormatter.time_of_day(
3123
- decodeResult,
3124
- DateTimeUtils.convertHHMMSSToTod(header[1])
3125
- );
3126
- } else {
3127
- ResultFormatter.time_of_day(
3128
- decodeResult,
3129
- DateTimeUtils.convertHHMMSSToTod(header[1])
3130
- );
2815
+ const data = message.text.split(",");
2816
+ if (data.length >= 8) {
2817
+ if (options.debug) {
2818
+ console.log("Label 44 Off Runway Report: groups");
2819
+ console.log(data);
3131
2820
  }
2821
+ ResultFormatter.position(
2822
+ decodeResult,
2823
+ CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
2824
+ );
2825
+ ResultFormatter.departureAirport(decodeResult, data[2]);
2826
+ ResultFormatter.arrivalAirport(decodeResult, data[3]);
2827
+ ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
2828
+ ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
2829
+ ResultFormatter.off(
2830
+ decodeResult,
2831
+ DateTimeUtils.convertHHMMSSToTod(data[5])
2832
+ );
3132
2833
  ResultFormatter.eta(
3133
2834
  decodeResult,
3134
- DateTimeUtils.convertHHMMSSToTod(parts[1])
2835
+ DateTimeUtils.convertHHMMSSToTod(data[6])
3135
2836
  );
3136
- const lat = parts[2].replaceAll(" ", "");
3137
- const lon = parts[3].replaceAll(" ", "");
3138
- if (lat[0] === "N" || lat[0] === "S") {
3139
- ResultFormatter.position(decodeResult, {
3140
- latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
3141
- longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
3142
- });
3143
- } else {
3144
- ResultFormatter.position(decodeResult, {
3145
- latitude: Number(lat),
3146
- longitude: Number(lon)
3147
- });
2837
+ const fuel = Number(data[7]);
2838
+ if (!isNaN(fuel)) {
2839
+ ResultFormatter.remainingFuel(decodeResult, Number(fuel));
2840
+ }
2841
+ if (data.length > 8) {
2842
+ ResultFormatter.unknownArr(decodeResult, data.slice(8));
3148
2843
  }
3149
- ResultFormatter.altitude(decodeResult, Number(parts[4]));
3150
- ResultFormatter.unknown(decodeResult, parts[5]);
3151
- ResultFormatter.unknown(decodeResult, parts[6]);
3152
- decodeResult.decoded = true;
3153
- decodeResult.decoder.decodeLevel = "partial";
3154
2844
  } else {
3155
2845
  if (options.debug) {
3156
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2846
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3157
2847
  }
3158
2848
  ResultFormatter.unknown(decodeResult, message.text);
3159
2849
  decodeResult.decoded = false;
3160
2850
  decodeResult.decoder.decodeLevel = "none";
2851
+ return decodeResult;
3161
2852
  }
2853
+ decodeResult.decoded = true;
2854
+ decodeResult.decoder.decodeLevel = "full";
3162
2855
  return decodeResult;
3163
2856
  }
3164
2857
  };
3165
2858
 
3166
- // lib/plugins/Label_2P_FM4.ts
3167
- var Label_2P_FM4 = class extends DecoderPlugin {
3168
- name = "label-2p-fm4";
2859
+ // lib/plugins/Label_44_ON.ts
2860
+ var Label_44_ON = class extends DecoderPlugin {
2861
+ name = "label-44-on";
3169
2862
  qualifiers() {
3170
2863
  return {
3171
- labels: ["2P"]
2864
+ labels: ["44"],
2865
+ preambles: ["00ON01", "00ON02", "00ON03", "ON01", "ON02", "ON03"]
3172
2866
  };
3173
2867
  }
3174
2868
  decode(message, options = {}) {
3175
- let decodeResult = this.defaultResult();
2869
+ const decodeResult = this.defaultResult();
3176
2870
  decodeResult.decoder.name = this.name;
3177
- decodeResult.formatted.description = "Flight Report";
2871
+ decodeResult.formatted.description = "On Runway Report";
3178
2872
  decodeResult.message = message;
3179
- const parts = message.text.split(",");
3180
- if (parts.length === 10) {
3181
- const header = parts[0].split("FM4");
3182
- if (header.length == 0) {
3183
- ResultFormatter.unknown(decodeResult, message.text);
3184
- decodeResult.decoded = false;
3185
- decodeResult.decoder.decodeLevel = "none";
3186
- return decodeResult;
3187
- }
3188
- if (header[0].length > 0) {
3189
- ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
3190
- ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2873
+ const data = message.text.split(",");
2874
+ if (data.length >= 7) {
2875
+ if (options.debug) {
2876
+ console.log("Label 44 On Runway Report: groups");
2877
+ console.log(data);
3191
2878
  }
3192
- ResultFormatter.departureAirport(decodeResult, header[1]);
3193
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
3194
- ResultFormatter.day(decodeResult, Number(parts[2].substring(0, 2)));
3195
- ResultFormatter.time_of_day(
2879
+ ResultFormatter.position(
3196
2880
  decodeResult,
3197
- DateTimeUtils.convertHHMMSSToTod(parts[2].substring(2))
2881
+ CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3198
2882
  );
3199
- ResultFormatter.eta(
2883
+ ResultFormatter.departureAirport(decodeResult, data[2]);
2884
+ ResultFormatter.arrivalAirport(decodeResult, data[3]);
2885
+ ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
2886
+ ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
2887
+ ResultFormatter.on(
3200
2888
  decodeResult,
3201
- DateTimeUtils.convertHHMMSSToTod(parts[3])
2889
+ DateTimeUtils.convertHHMMSSToTod(data[5])
3202
2890
  );
3203
- ResultFormatter.position(decodeResult, {
3204
- latitude: Number(parts[4].replaceAll(" ", "")),
3205
- longitude: Number(parts[5].replaceAll(" ", ""))
3206
- });
3207
- ResultFormatter.altitude(decodeResult, Number(parts[6]));
3208
- ResultFormatter.heading(decodeResult, Number(parts[7]));
3209
- ResultFormatter.unknown(decodeResult, parts[8]);
3210
- ResultFormatter.unknown(decodeResult, parts[9]);
3211
- decodeResult.decoded = true;
3212
- decodeResult.decoder.decodeLevel = "partial";
2891
+ const fuel = Number(data[6]);
2892
+ if (!isNaN(fuel)) {
2893
+ ResultFormatter.remainingFuel(decodeResult, Number(fuel));
2894
+ }
2895
+ if (data.length > 7) {
2896
+ ResultFormatter.unknownArr(decodeResult, data.slice(7));
2897
+ }
3213
2898
  } else {
3214
2899
  if (options.debug) {
3215
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2900
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3216
2901
  }
3217
2902
  ResultFormatter.unknown(decodeResult, message.text);
3218
2903
  decodeResult.decoded = false;
3219
2904
  decodeResult.decoder.decodeLevel = "none";
2905
+ return decodeResult;
3220
2906
  }
2907
+ decodeResult.decoded = true;
2908
+ decodeResult.decoder.decodeLevel = "full";
3221
2909
  return decodeResult;
3222
2910
  }
3223
2911
  };
3224
2912
 
3225
- // lib/plugins/Label_2P_FM5.ts
3226
- var Label_2P_FM5 = class extends DecoderPlugin {
3227
- name = "label-2p-fm5";
2913
+ // lib/plugins/Label_44_POS.ts
2914
+ var Label_44_POS = class extends DecoderPlugin {
2915
+ name = "label-44-pos";
3228
2916
  qualifiers() {
3229
2917
  return {
3230
- labels: ["2P"]
2918
+ labels: ["44"],
2919
+ preambles: ["00POS01", "00POS02", "00POS03", "POS01", "POS02", "POS03"]
3231
2920
  };
3232
2921
  }
3233
2922
  decode(message, options = {}) {
3234
- let decodeResult = this.defaultResult();
2923
+ const decodeResult = this.defaultResult();
3235
2924
  decodeResult.decoder.name = this.name;
3236
- decodeResult.formatted.description = "Flight Report";
2925
+ decodeResult.formatted.description = "Position Report";
3237
2926
  decodeResult.message = message;
3238
- const parts = message.text.split(",");
3239
- if (parts.length === 12) {
3240
- const header = parts[0].split("FM5 ");
3241
- if (header.length == 0) {
3242
- ResultFormatter.unknown(decodeResult, message.text);
3243
- decodeResult.decoded = false;
3244
- decodeResult.decoder.decodeLevel = "none";
3245
- return decodeResult;
2927
+ const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
2928
+ const results = message.text.match(regex);
2929
+ if (results?.groups) {
2930
+ if (options.debug) {
2931
+ console.log("Label 44 Position Report: groups");
2932
+ console.log(results.groups);
3246
2933
  }
3247
- ResultFormatter.departureAirport(decodeResult, header[1]);
3248
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2934
+ ResultFormatter.position(
2935
+ decodeResult,
2936
+ CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
2937
+ results.groups.unsplit_coords
2938
+ )
2939
+ );
2940
+ const flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? 0 : Number(results.groups.flight_level_or_ground);
2941
+ ResultFormatter.month(
2942
+ decodeResult,
2943
+ Number(results.groups.current_date.substring(0, 2))
2944
+ );
2945
+ ResultFormatter.day(
2946
+ decodeResult,
2947
+ Number(results.groups.current_date.substring(2, 4))
2948
+ );
3249
2949
  ResultFormatter.time_of_day(
3250
2950
  decodeResult,
3251
- DateTimeUtils.convertHHMMSSToTod(parts[2])
2951
+ DateTimeUtils.convertHHMMSSToTod(results.groups.current_time + "00")
3252
2952
  );
3253
2953
  ResultFormatter.eta(
3254
2954
  decodeResult,
3255
- DateTimeUtils.convertHHMMSSToTod(parts[3])
2955
+ DateTimeUtils.convertHHMMSSToTod(results.groups.eta_time + "00")
3256
2956
  );
3257
- ResultFormatter.position(decodeResult, {
3258
- latitude: Number(parts[4].replaceAll(" ", "")),
3259
- longitude: Number(parts[5].replaceAll(" ", ""))
3260
- });
3261
- ResultFormatter.altitude(decodeResult, Number(parts[6]));
3262
- ResultFormatter.unknown(decodeResult, parts[7]);
3263
- ResultFormatter.unknown(decodeResult, parts[8]);
3264
- ResultFormatter.unknown(decodeResult, parts[9]);
3265
- ResultFormatter.flightNumber(decodeResult, parts[10].trim());
3266
- ResultFormatter.unknown(decodeResult, parts[11]);
3267
- decodeResult.decoded = true;
3268
- decodeResult.decoder.decodeLevel = "partial";
3269
- } else {
3270
- if (options.debug) {
3271
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2957
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
2958
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
3272
2959
  }
3273
- ResultFormatter.unknown(decodeResult, message.text);
3274
- decodeResult.decoded = false;
3275
- decodeResult.decoder.decodeLevel = "none";
3276
- }
3277
- return decodeResult;
3278
- }
3279
- };
3280
-
3281
- // lib/plugins/Label_2P_POS.ts
3282
- var Label_2P_POS = class extends DecoderPlugin {
3283
- name = "label-2p-pos";
3284
- qualifiers() {
3285
- return {
3286
- labels: ["2P"]
3287
- };
3288
- }
3289
- decode(message, options = {}) {
3290
- let decodeResult = this.defaultResult();
3291
- decodeResult.decoder.name = this.name;
3292
- decodeResult.message = message;
3293
- const msg = message.text.replace(/\n|\r/g, "");
3294
- const parts = msg.split("/");
3295
- let decoded = false;
3296
- if (parts[0].length > 3) {
3297
- decoded = H1Helper.decodeH1Message(
2960
+ ResultFormatter.departureAirport(
3298
2961
  decodeResult,
3299
- msg.slice(parts[0].length - 3)
2962
+ results.groups.departure_icao
3300
2963
  );
3301
- decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
3302
- } else {
3303
- decoded = H1Helper.decodeH1Message(decodeResult, msg);
3304
- }
3305
- decodeResult.decoded = decoded;
3306
- decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
3307
- if (decodeResult.formatted.items.length === 0) {
3308
- if (options.debug) {
3309
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
3310
- }
3311
- ResultFormatter.unknown(decodeResult, message.text);
3312
- decodeResult.decoded = false;
3313
- decodeResult.decoder.decodeLevel = "none";
2964
+ ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
2965
+ ResultFormatter.altitude(decodeResult, flight_level * 100);
3314
2966
  }
2967
+ decodeResult.decoded = true;
2968
+ decodeResult.decoder.decodeLevel = "full";
3315
2969
  return decodeResult;
3316
2970
  }
3317
2971
  };
3318
2972
 
3319
- // lib/plugins/Label_24_Slash.ts
3320
- var Label_24_Slash = class extends DecoderPlugin {
3321
- name = "label-24-slash";
3322
- qualifiers() {
3323
- return {
3324
- labels: ["24"],
3325
- preambles: ["/"]
3326
- };
3327
- }
3328
- decode(message, options = {}) {
3329
- const decodeResult = this.defaultResult();
3330
- decodeResult.decoder.name = this.name;
3331
- decodeResult.formatted.description = "Position Report";
3332
- decodeResult.message = message;
3333
- const fields = message.text.split("/");
3334
- if (fields.length == 10 && fields[0] == "" && fields[9] == "") {
3335
- const ddmmyy = fields[1].substring(2, 4) + fields[1].substring(4, 6) + fields[1].substring(0, 2);
3336
- const hhmmss = fields[2] + "00";
3337
- decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(
3338
- hhmmss,
3339
- ddmmyy
3340
- );
3341
- ResultFormatter.flightNumber(decodeResult, fields[3]);
3342
- ResultFormatter.altitude(decodeResult, Number(fields[4]));
3343
- const lat = fields[5];
3344
- const lon = fields[6];
3345
- const position = {
3346
- latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
3347
- longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
3348
- };
3349
- ResultFormatter.position(decodeResult, position);
3350
- ResultFormatter.eta(
3351
- decodeResult,
3352
- DateTimeUtils.convertHHMMSSToTod(fields[8])
3353
- );
3354
- ResultFormatter.unknown(decodeResult, fields[7]);
3355
- decodeResult.decoded = true;
3356
- decodeResult.decoder.decodeLevel = "partial";
3357
- } else {
3358
- if (options.debug) {
3359
- console.log(
3360
- `DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`
3361
- );
2973
+ // lib/utils/flight_plan_utils.ts
2974
+ var FlightPlanUtils = class _FlightPlanUtils {
2975
+ /**
2976
+ * Processes flight plan data
2977
+ *
2978
+ * Expected format is [header, key1, val1, ... keyN, valN]
2979
+ *
2980
+ * @param decodeResult - results
2981
+ * @param data - original message split by ':'
2982
+ * @returns whether all fields were processed or not
2983
+ */
2984
+ static processFlightPlan(decodeResult, data) {
2985
+ let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
2986
+ for (let i = 1; i < data.length; i += 2) {
2987
+ const key = data[i];
2988
+ const value = data[i + 1];
2989
+ switch (key) {
2990
+ case "A":
2991
+ _FlightPlanUtils.addProcedure(decodeResult, value, "arrival");
2992
+ break;
2993
+ case "AA":
2994
+ addArrivalAirport(decodeResult, value);
2995
+ break;
2996
+ case "AP":
2997
+ _FlightPlanUtils.addProcedure(decodeResult, value, "approach");
2998
+ break;
2999
+ case "CR":
3000
+ addCompanyRoute(decodeResult, value);
3001
+ break;
3002
+ case "D":
3003
+ _FlightPlanUtils.addProcedure(decodeResult, value, "departure");
3004
+ break;
3005
+ case "DA":
3006
+ addDepartureAirport(decodeResult, value);
3007
+ break;
3008
+ case "F":
3009
+ addRoute(decodeResult, value);
3010
+ break;
3011
+ case "FP":
3012
+ ResultFormatter.flightPlan(decodeResult, value.trim());
3013
+ break;
3014
+ case "R":
3015
+ addRunway(decodeResult, value);
3016
+ break;
3017
+ // case 'WS': // something about routes, has altitude, so current parsing won't work
3018
+ // break;
3019
+ default:
3020
+ if (allKnownFields) {
3021
+ decodeResult.remaining.text = "";
3022
+ allKnownFields = false;
3023
+ }
3024
+ decodeResult.remaining.text += `:${key}:${value}`;
3025
+ decodeResult.decoder.decodeLevel = "partial";
3362
3026
  }
3363
- decodeResult.decoded = false;
3364
- decodeResult.decoder.decodeLevel = "none";
3365
3027
  }
3366
- return decodeResult;
3028
+ return allKnownFields;
3029
+ }
3030
+ static parseHeader(decodeResult, header) {
3031
+ let allKnownFields = true;
3032
+ if (header.startsWith("RF")) {
3033
+ decodeResult.formatted.items.push({
3034
+ type: "status",
3035
+ code: "ROUTE_STATUS",
3036
+ label: "Route Status",
3037
+ value: "Route Filed"
3038
+ });
3039
+ decodeResult.raw.route_status = "RF";
3040
+ if (header.length > 2) {
3041
+ addRoute(decodeResult, header.substring(2));
3042
+ }
3043
+ } else if (header.startsWith("RP")) {
3044
+ decodeResult.raw.route_status = "RP";
3045
+ decodeResult.formatted.items.push({
3046
+ type: "status",
3047
+ code: "ROUTE_STATUS",
3048
+ label: "Route Status",
3049
+ value: "Route Planned"
3050
+ });
3051
+ decodeResult.raw.route_status = header;
3052
+ } else if (header.startsWith("RI")) {
3053
+ decodeResult.raw.route_status = "RI";
3054
+ decodeResult.formatted.items.push({
3055
+ type: "status",
3056
+ code: "ROUTE_STATUS",
3057
+ label: "Route Status",
3058
+ value: "Route Inactive"
3059
+ });
3060
+ } else if (header.startsWith("RM")) {
3061
+ decodeResult.raw.route_status = "RM";
3062
+ decodeResult.formatted.items.push({
3063
+ type: "status",
3064
+ code: "ROUTE_STATUS",
3065
+ label: "Route Status",
3066
+ value: "Route Mapped"
3067
+ });
3068
+ } else if (header.startsWith("RS")) {
3069
+ decodeResult.raw.route_status = "RS";
3070
+ decodeResult.formatted.items.push({
3071
+ type: "status",
3072
+ code: "ROUTE_STATUS",
3073
+ label: "Route Status",
3074
+ value: "Route Saved"
3075
+ });
3076
+ } else {
3077
+ decodeResult.remaining.text += header;
3078
+ allKnownFields = false;
3079
+ }
3080
+ return allKnownFields;
3081
+ }
3082
+ static addProcedure(decodeResult, value, type) {
3083
+ if (decodeResult.raw.procedures === void 0) {
3084
+ decodeResult.raw.procedures = [];
3085
+ }
3086
+ const data = value.split(".");
3087
+ let waypoints;
3088
+ if (data.length > 1) {
3089
+ waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
3090
+ }
3091
+ const route = { name: data[0], waypoints };
3092
+ decodeResult.raw.procedures.push({ type, route });
3093
+ const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
3094
+ decodeResult.formatted.items.push({
3095
+ type: "procedure",
3096
+ code: "proc",
3097
+ label: `${procedureName} Procedure`,
3098
+ value: RouteUtils.routeToString(route)
3099
+ });
3367
3100
  }
3368
3101
  };
3102
+ function addArrivalAirport(decodeResult, value) {
3103
+ ResultFormatter.arrivalAirport(decodeResult, value);
3104
+ }
3105
+ function addDepartureAirport(decodeResult, value) {
3106
+ ResultFormatter.departureAirport(decodeResult, value);
3107
+ }
3108
+ function addRunway(decodeResult, value) {
3109
+ if (value.length === 8) {
3110
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
3111
+ }
3112
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
3113
+ }
3114
+ function addRoute(decodeResult, value) {
3115
+ const route = value.split(".");
3116
+ ResultFormatter.route(decodeResult, {
3117
+ waypoints: route.map((leg) => RouteUtils.getWaypoint(leg))
3118
+ });
3119
+ }
3120
+ function addCompanyRoute(decodeResult, value) {
3121
+ const segments = value.split(".");
3122
+ const parens_idx = segments[0].indexOf("(");
3123
+ let name;
3124
+ let runway;
3125
+ if (parens_idx === -1) {
3126
+ name = segments[0];
3127
+ } else {
3128
+ name = segments[0].slice(0, parens_idx);
3129
+ runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
3130
+ }
3131
+ let waypoints;
3132
+ if (segments.length > 1) {
3133
+ waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
3134
+ }
3135
+ decodeResult.raw.company_route = {
3136
+ name,
3137
+ runway,
3138
+ waypoints
3139
+ };
3140
+ decodeResult.formatted.items.push({
3141
+ type: "company_route",
3142
+ code: "CR",
3143
+ label: "Company Route",
3144
+ value: RouteUtils.routeToString(decodeResult.raw.company_route)
3145
+ });
3146
+ }
3369
3147
 
3370
- // lib/plugins/Label_30_Slash_EA.ts
3371
- var Label_30_Slash_EA = class extends DecoderPlugin {
3372
- name = "label-30-slash-ea";
3148
+ // lib/plugins/Label_44_Slash.ts
3149
+ var Label_44_Slash = class extends DecoderPlugin {
3150
+ name = "label-44-slash";
3373
3151
  qualifiers() {
3374
3152
  return {
3375
- labels: ["30"],
3376
- preambles: ["/EA"]
3153
+ labels: ["44"],
3154
+ preambles: [" /FB"]
3377
3155
  };
3378
3156
  }
3379
3157
  decode(message, options = {}) {
3380
3158
  const decodeResult = this.defaultResult();
3381
3159
  decodeResult.decoder.name = this.name;
3382
- decodeResult.formatted.description = "ETA Report";
3160
+ decodeResult.formatted.description = "Flight Briefing";
3383
3161
  decodeResult.message = message;
3384
- const results = message.text.split(/\n|\//).slice(1);
3385
- if (results) {
3162
+ const fields = message.text.split("/");
3163
+ if (fields.length !== 4) {
3386
3164
  if (options.debug) {
3387
- console.log("Label 30 EA: results");
3388
- console.log(results);
3165
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3389
3166
  }
3167
+ ResultFormatter.unknown(decodeResult, message.text);
3168
+ decodeResult.decoded = false;
3169
+ decodeResult.decoder.decodeLevel = "none";
3170
+ return decodeResult;
3390
3171
  }
3391
- ResultFormatter.eta(
3392
- decodeResult,
3393
- DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4))
3394
- );
3395
- if (results[1].substring(0, 2) === "DS") {
3396
- ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6));
3397
- ResultFormatter.unknown(decodeResult, "/".concat(results[2]));
3398
- } else {
3399
- ResultFormatter.unknown(
3172
+ ResultFormatter.unknownArr(decodeResult, fields.slice(0, 2), "/");
3173
+ const data = fields[3].split(",");
3174
+ if (data.length >= 6) {
3175
+ if (options.debug) {
3176
+ console.log("Label 44 Slash: groups");
3177
+ console.log(data);
3178
+ }
3179
+ ResultFormatter.position(decodeResult, {
3180
+ latitude: (data[0].charAt(0) === "S" ? -1 : 1) * parseFloat(data[0].slice(1).trim()),
3181
+ longitude: (data[1].charAt(0) === "W" ? -1 : 1) * parseFloat(data[1].slice(1).trim())
3182
+ });
3183
+ ResultFormatter.flightNumber(decodeResult, data[2]);
3184
+ ResultFormatter.unknown(decodeResult, data[3]);
3185
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
3186
+ ResultFormatter.eta(
3400
3187
  decodeResult,
3401
- "/".concat(results[1], "/", results[2])
3188
+ DateTimeUtils.convertHHMMSSToTod(data[5])
3402
3189
  );
3190
+ if (data.length === 18) {
3191
+ ResultFormatter.unknownArr(decodeResult, data.slice(6, 8), ",");
3192
+ ResultFormatter.remainingFuel(decodeResult, parseFloat(data[8]));
3193
+ ResultFormatter.unknownArr(decodeResult, data.slice(9, 11), ",");
3194
+ ResultFormatter.arrivalRunway(decodeResult, data[11]);
3195
+ FlightPlanUtils.addProcedure(decodeResult, data[12], "arrival");
3196
+ ResultFormatter.unknownArr(decodeResult, data.slice(13, 18), ",");
3197
+ }
3198
+ } else {
3199
+ if (options.debug) {
3200
+ console.log(`Decoder: Unknown 44 message: ${message.text}`);
3201
+ }
3202
+ ResultFormatter.unknown(decodeResult, message.text);
3203
+ decodeResult.decoded = false;
3204
+ decodeResult.decoder.decodeLevel = "none";
3205
+ return decodeResult;
3403
3206
  }
3404
3207
  decodeResult.decoded = true;
3405
3208
  decodeResult.decoder.decodeLevel = "partial";
@@ -3407,344 +3210,396 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
3407
3210
  }
3408
3211
  };
3409
3212
 
3410
- // lib/plugins/Label_44_ETA.ts
3411
- var Label_44_ETA = class extends DecoderPlugin {
3412
- name = "label-44-eta";
3213
+ // lib/plugins/Label_4A.ts
3214
+ var Label_4A = class extends DecoderPlugin {
3215
+ name = "label-4a";
3413
3216
  qualifiers() {
3414
3217
  return {
3415
- labels: ["44"],
3416
- preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
3218
+ labels: ["4A"]
3417
3219
  };
3418
3220
  }
3419
3221
  decode(message, options = {}) {
3420
3222
  const decodeResult = this.defaultResult();
3421
3223
  decodeResult.decoder.name = this.name;
3422
- decodeResult.formatted.description = "ETA Report";
3423
3224
  decodeResult.message = message;
3424
- const data = message.text.split(",");
3425
- if (data.length >= 9) {
3426
- if (options.debug) {
3427
- console.log("Label 44 ETA Report: groups");
3428
- console.log(data);
3429
- }
3430
- ResultFormatter.position(
3431
- decodeResult,
3432
- CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3433
- );
3434
- ResultFormatter.altitude(decodeResult, 100 * Number(data[2]));
3435
- ResultFormatter.departureAirport(decodeResult, data[3]);
3436
- ResultFormatter.arrivalAirport(decodeResult, data[4]);
3437
- ResultFormatter.month(decodeResult, Number(data[5].substring(0, 2)));
3438
- ResultFormatter.day(decodeResult, Number(data[5].substring(2, 4)));
3225
+ decodeResult.formatted.description = "Latest New Format";
3226
+ decodeResult.decoded = true;
3227
+ const fields = message.text.split(",");
3228
+ if (fields.length === 11) {
3439
3229
  ResultFormatter.time_of_day(
3440
3230
  decodeResult,
3441
- DateTimeUtils.convertHHMMSSToTod(data[6])
3442
- );
3443
- ResultFormatter.eta(
3444
- decodeResult,
3445
- DateTimeUtils.convertHHMMSSToTod(data[7])
3231
+ DateTimeUtils.convertHHMMSSToTod(fields[0])
3446
3232
  );
3447
- const fuel = Number(data[8]);
3448
- if (!isNaN(fuel)) {
3449
- ResultFormatter.remainingFuel(decodeResult, Number(fuel));
3450
- }
3451
- if (data.length > 9) {
3452
- ResultFormatter.unknownArr(decodeResult, data.slice(9));
3233
+ ResultFormatter.tail(decodeResult, fields[2].replace(".", ""));
3234
+ if (fields[3]) ResultFormatter.callsign(decodeResult, fields[3]);
3235
+ ResultFormatter.departureAirport(decodeResult, fields[4]);
3236
+ ResultFormatter.arrivalAirport(decodeResult, fields[5]);
3237
+ ResultFormatter.unknownArr(decodeResult, fields.slice(8));
3238
+ } else if (fields.length === 6) {
3239
+ if (fields[0].match(/^[NS]/)) {
3240
+ ResultFormatter.position(
3241
+ decodeResult,
3242
+ CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13))
3243
+ );
3244
+ let wp1 = {
3245
+ name: fields[0].substring(13).trim(),
3246
+ time: DateTimeUtils.convertHHMMSSToTod(fields[1].substring(0, 6)),
3247
+ timeFormat: "tod"
3248
+ };
3249
+ ResultFormatter.altitude(
3250
+ decodeResult,
3251
+ Number(fields[1].substring(6, 9)) * 100
3252
+ );
3253
+ let wp2 = {
3254
+ name: fields[1].substring(9).trim(),
3255
+ time: DateTimeUtils.convertHHMMSSToTod(fields[2]),
3256
+ timeFormat: "tod"
3257
+ };
3258
+ ResultFormatter.route(decodeResult, { waypoints: [wp1, wp2] });
3259
+ ResultFormatter.temperature(decodeResult, fields[3]);
3260
+ ResultFormatter.unknownArr(decodeResult, fields.slice(4));
3261
+ } else {
3262
+ ResultFormatter.time_of_day(
3263
+ decodeResult,
3264
+ DateTimeUtils.convertHHMMSSToTod(fields[0])
3265
+ );
3266
+ ResultFormatter.eta(
3267
+ decodeResult,
3268
+ DateTimeUtils.convertHHMMSSToTod(fields[1])
3269
+ );
3270
+ ResultFormatter.unknown(decodeResult, fields[2]);
3271
+ ResultFormatter.altitude(decodeResult, Number(fields[3]));
3272
+ ResultFormatter.position(
3273
+ decodeResult,
3274
+ CoordinateUtils.decodeStringCoordinates(
3275
+ (fields[4] + fields[5]).replace(/[ \.]/g, "")
3276
+ )
3277
+ );
3453
3278
  }
3454
3279
  } else {
3455
- if (options.debug) {
3456
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3457
- }
3458
- ResultFormatter.unknown(decodeResult, message.text);
3459
3280
  decodeResult.decoded = false;
3281
+ ResultFormatter.unknown(decodeResult, message.text);
3282
+ }
3283
+ if (decodeResult.decoded) {
3284
+ if (!decodeResult.remaining.text)
3285
+ decodeResult.decoder.decodeLevel = "full";
3286
+ else decodeResult.decoder.decodeLevel = "partial";
3287
+ } else {
3460
3288
  decodeResult.decoder.decodeLevel = "none";
3461
- return decodeResult;
3462
3289
  }
3463
- decodeResult.decoded = true;
3464
- decodeResult.decoder.decodeLevel = "full";
3465
3290
  return decodeResult;
3466
3291
  }
3467
3292
  };
3468
3293
 
3469
- // lib/plugins/Label_44_IN.ts
3470
- var Label_44_IN = class extends DecoderPlugin {
3471
- name = "label-44-in";
3294
+ // lib/plugins/Label_4A_01.ts
3295
+ var Label_4A_01 = class extends DecoderPlugin {
3296
+ name = "label-4a-01";
3472
3297
  qualifiers() {
3473
3298
  return {
3474
- labels: ["44"],
3475
- preambles: ["00IN01", "00IN02", "00IN03", "IN01", "IN02", "IN03"]
3299
+ labels: ["4A"],
3300
+ preambles: ["01"]
3476
3301
  };
3477
3302
  }
3478
3303
  decode(message, options = {}) {
3479
3304
  const decodeResult = this.defaultResult();
3480
3305
  decodeResult.decoder.name = this.name;
3481
- decodeResult.formatted.description = "In Air Report";
3482
3306
  decodeResult.message = message;
3483
- const data = message.text.split(",");
3484
- if (data.length >= 7) {
3485
- if (options.debug) {
3486
- console.log("Label 44 In Air Report: groups");
3487
- console.log(data);
3488
- }
3489
- ResultFormatter.position(
3490
- decodeResult,
3491
- CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3492
- );
3493
- ResultFormatter.departureAirport(decodeResult, data[2]);
3494
- ResultFormatter.arrivalAirport(decodeResult, data[3]);
3495
- ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
3496
- ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
3497
- ResultFormatter.in(
3307
+ decodeResult.formatted.description = "Latest New Format";
3308
+ decodeResult.decoded = true;
3309
+ let rgx = message.text.match(
3310
+ /^01([A-Z]{2})([A-Z]{2})\s*(\w+)\/(\d{6})([A-Z]{4})([A-Z]{4})\r\n([+-]\s*\d+)(\d{3}\.\d)([+-]\s*\d+\.\d)/
3311
+ );
3312
+ if (rgx) {
3313
+ ResultFormatter.state_change(decodeResult, rgx[1], rgx[2]);
3314
+ ResultFormatter.callsign(decodeResult, rgx[3]);
3315
+ ResultFormatter.time_of_day(
3498
3316
  decodeResult,
3499
- DateTimeUtils.convertHHMMSSToTod(data[5])
3317
+ DateTimeUtils.convertHHMMSSToTod(rgx[4] + "00")
3500
3318
  );
3501
- const fuel = Number(data[6]);
3502
- if (!isNaN(fuel)) {
3503
- ResultFormatter.remainingFuel(decodeResult, Number(fuel));
3504
- }
3505
- if (data.length > 7) {
3506
- ResultFormatter.unknownArr(decodeResult, data.slice(7));
3507
- }
3319
+ ResultFormatter.departureAirport(decodeResult, rgx[5]);
3320
+ ResultFormatter.arrivalAirport(decodeResult, rgx[6]);
3321
+ ResultFormatter.altitude(decodeResult, Number(rgx[7].replace(/ /g, "")));
3322
+ ResultFormatter.unknown(decodeResult, rgx[8]);
3323
+ ResultFormatter.temperature(decodeResult, rgx[9].replace(/ /g, ""));
3508
3324
  } else {
3509
- if (options.debug) {
3510
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3511
- }
3512
- ResultFormatter.unknown(decodeResult, message.text);
3513
3325
  decodeResult.decoded = false;
3326
+ ResultFormatter.unknown(decodeResult, message.text);
3327
+ }
3328
+ if (decodeResult.decoded) {
3329
+ if (!decodeResult.remaining.text)
3330
+ decodeResult.decoder.decodeLevel = "full";
3331
+ else decodeResult.decoder.decodeLevel = "partial";
3332
+ } else {
3514
3333
  decodeResult.decoder.decodeLevel = "none";
3515
- return decodeResult;
3516
3334
  }
3517
- decodeResult.decoded = true;
3518
- decodeResult.decoder.decodeLevel = "full";
3519
3335
  return decodeResult;
3520
3336
  }
3521
3337
  };
3522
3338
 
3523
- // lib/plugins/Label_44_OFF.ts
3524
- var Label_44_OFF = class extends DecoderPlugin {
3525
- name = "label-44-off";
3339
+ // lib/plugins/Label_4A_DIS.ts
3340
+ var Label_4A_DIS = class extends DecoderPlugin {
3341
+ name = "label-4a-dis";
3526
3342
  qualifiers() {
3527
3343
  return {
3528
- labels: ["44"],
3529
- preambles: ["00OFF01", "00OFF02", "00OFF03", "OFF01", "OFF02", "OFF03"]
3344
+ labels: ["4A"],
3345
+ preambles: ["DIS"]
3530
3346
  };
3531
3347
  }
3532
3348
  decode(message, options = {}) {
3533
3349
  const decodeResult = this.defaultResult();
3534
3350
  decodeResult.decoder.name = this.name;
3535
- decodeResult.formatted.description = "Off Runway Report";
3536
3351
  decodeResult.message = message;
3537
- const data = message.text.split(",");
3538
- if (data.length >= 8) {
3539
- if (options.debug) {
3540
- console.log("Label 44 Off Runway Report: groups");
3541
- console.log(data);
3542
- }
3543
- ResultFormatter.position(
3544
- decodeResult,
3545
- CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3546
- );
3547
- ResultFormatter.departureAirport(decodeResult, data[2]);
3548
- ResultFormatter.arrivalAirport(decodeResult, data[3]);
3549
- ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
3550
- ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
3551
- ResultFormatter.off(
3552
- decodeResult,
3553
- DateTimeUtils.convertHHMMSSToTod(data[5])
3554
- );
3555
- ResultFormatter.eta(
3556
- decodeResult,
3557
- DateTimeUtils.convertHHMMSSToTod(data[6])
3558
- );
3559
- const fuel = Number(data[7]);
3560
- if (!isNaN(fuel)) {
3561
- ResultFormatter.remainingFuel(decodeResult, Number(fuel));
3562
- }
3563
- if (data.length > 8) {
3564
- ResultFormatter.unknownArr(decodeResult, data.slice(8));
3565
- }
3352
+ decodeResult.formatted.description = "Latest New Format";
3353
+ decodeResult.decoded = true;
3354
+ const fields = message.text.split(",");
3355
+ ResultFormatter.time_of_day(
3356
+ decodeResult,
3357
+ DateTimeUtils.convertHHMMSSToTod(fields[1].substring(2) + "00")
3358
+ );
3359
+ ResultFormatter.callsign(decodeResult, fields[2]);
3360
+ ResultFormatter.freetext(decodeResult, fields.slice(3).join(""));
3361
+ if (decodeResult.decoded) {
3362
+ if (!decodeResult.remaining.text)
3363
+ decodeResult.decoder.decodeLevel = "full";
3364
+ else decodeResult.decoder.decodeLevel = "partial";
3566
3365
  } else {
3567
- if (options.debug) {
3568
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3569
- }
3570
- ResultFormatter.unknown(decodeResult, message.text);
3571
- decodeResult.decoded = false;
3572
3366
  decodeResult.decoder.decodeLevel = "none";
3573
- return decodeResult;
3574
3367
  }
3575
- decodeResult.decoded = true;
3576
- decodeResult.decoder.decodeLevel = "full";
3577
3368
  return decodeResult;
3578
3369
  }
3579
3370
  };
3580
3371
 
3581
- // lib/plugins/Label_44_ON.ts
3582
- var Label_44_ON = class extends DecoderPlugin {
3583
- name = "label-44-on";
3372
+ // lib/plugins/Label_4A_DOOR.ts
3373
+ var Label_4A_DOOR = class extends DecoderPlugin {
3374
+ name = "label-4a-door";
3584
3375
  qualifiers() {
3585
3376
  return {
3586
- labels: ["44"],
3587
- preambles: ["00ON01", "00ON02", "00ON03", "ON01", "ON02", "ON03"]
3377
+ labels: ["4A"],
3378
+ preambles: ["DOOR"]
3588
3379
  };
3589
3380
  }
3590
3381
  decode(message, options = {}) {
3591
3382
  const decodeResult = this.defaultResult();
3592
3383
  decodeResult.decoder.name = this.name;
3593
- decodeResult.formatted.description = "On Runway Report";
3594
3384
  decodeResult.message = message;
3595
- const data = message.text.split(",");
3596
- if (data.length >= 7) {
3597
- if (options.debug) {
3598
- console.log("Label 44 On Runway Report: groups");
3599
- console.log(data);
3600
- }
3601
- ResultFormatter.position(
3385
+ decodeResult.formatted.description = "Latest New Format";
3386
+ decodeResult.decoded = true;
3387
+ const fields = message.text.split(" ");
3388
+ if (fields.length === 3) {
3389
+ ResultFormatter.door_event(
3602
3390
  decodeResult,
3603
- CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[1])
3391
+ fields[0].split("/")[1],
3392
+ fields[1]
3604
3393
  );
3605
- ResultFormatter.departureAirport(decodeResult, data[2]);
3606
- ResultFormatter.arrivalAirport(decodeResult, data[3]);
3607
- ResultFormatter.month(decodeResult, Number(data[4].substring(0, 2)));
3608
- ResultFormatter.day(decodeResult, Number(data[4].substring(2, 4)));
3609
- ResultFormatter.on(
3394
+ ResultFormatter.time_of_day(
3610
3395
  decodeResult,
3611
- DateTimeUtils.convertHHMMSSToTod(data[5])
3396
+ DateTimeUtils.convertHHMMSSToTod(fields[2] + "00")
3612
3397
  );
3613
- const fuel = Number(data[6]);
3614
- if (!isNaN(fuel)) {
3615
- ResultFormatter.remainingFuel(decodeResult, Number(fuel));
3616
- }
3617
- if (data.length > 7) {
3618
- ResultFormatter.unknownArr(decodeResult, data.slice(7));
3619
- }
3620
3398
  } else {
3621
- if (options.debug) {
3622
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3623
- }
3624
- ResultFormatter.unknown(decodeResult, message.text);
3625
3399
  decodeResult.decoded = false;
3626
- decodeResult.decoder.decodeLevel = "none";
3627
- return decodeResult;
3400
+ ResultFormatter.unknown(decodeResult, message.text);
3401
+ }
3402
+ if (decodeResult.decoded) {
3403
+ if (!decodeResult.remaining.text)
3404
+ decodeResult.decoder.decodeLevel = "full";
3405
+ else decodeResult.decoder.decodeLevel = "partial";
3406
+ } else {
3407
+ decodeResult.decoder.decodeLevel = "none";
3628
3408
  }
3409
+ return decodeResult;
3410
+ }
3411
+ };
3412
+
3413
+ // lib/plugins/Label_4A_Slash_01.ts
3414
+ var Label_4A_Slash_01 = class extends DecoderPlugin {
3415
+ name = "label-4a-slash-01";
3416
+ qualifiers() {
3417
+ return {
3418
+ labels: ["4A"],
3419
+ preambles: ["/01"]
3420
+ };
3421
+ }
3422
+ decode(message, options = {}) {
3423
+ const decodeResult = this.defaultResult();
3424
+ decodeResult.decoder.name = this.name;
3425
+ decodeResult.message = message;
3426
+ decodeResult.formatted.description = "Latest New Format";
3629
3427
  decodeResult.decoded = true;
3630
- decodeResult.decoder.decodeLevel = "full";
3428
+ if (message.text.length === 5 && message.text.substring(0, 4) === "/01-") {
3429
+ ResultFormatter.unknown(decodeResult, message.text.substring(4));
3430
+ } else {
3431
+ decodeResult.decoded = false;
3432
+ ResultFormatter.unknown(decodeResult, message.text);
3433
+ }
3434
+ if (decodeResult.decoded) {
3435
+ if (!decodeResult.remaining.text)
3436
+ decodeResult.decoder.decodeLevel = "full";
3437
+ else decodeResult.decoder.decodeLevel = "partial";
3438
+ } else {
3439
+ decodeResult.decoder.decodeLevel = "none";
3440
+ }
3631
3441
  return decodeResult;
3632
3442
  }
3633
3443
  };
3634
3444
 
3635
- // lib/plugins/Label_44_POS.ts
3636
- var Label_44_POS = class extends DecoderPlugin {
3637
- name = "label-44-pos";
3445
+ // lib/plugins/Label_4N.ts
3446
+ var Label_4N = class extends DecoderPlugin {
3447
+ name = "label-4n";
3638
3448
  qualifiers() {
3639
3449
  return {
3640
- labels: ["44"],
3641
- preambles: ["00POS01", "00POS02", "00POS03", "POS01", "POS02", "POS03"]
3450
+ labels: ["4N"]
3642
3451
  };
3643
3452
  }
3644
3453
  decode(message, options = {}) {
3645
3454
  const decodeResult = this.defaultResult();
3646
3455
  decodeResult.decoder.name = this.name;
3647
- decodeResult.formatted.description = "Position Report";
3648
3456
  decodeResult.message = message;
3649
- const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
3650
- const results = message.text.match(regex);
3651
- if (results?.groups) {
3652
- if (options.debug) {
3653
- console.log("Label 44 Position Report: groups");
3654
- console.log(results.groups);
3655
- }
3457
+ decodeResult.formatted.description = "Airline Defined";
3458
+ decodeResult.decoded = true;
3459
+ const text = message.text;
3460
+ const fields = text.split(",");
3461
+ if (text.length === 51) {
3462
+ decodeResult.raw.day = text.substring(0, 2);
3463
+ ResultFormatter.departureAirport(decodeResult, text.substring(8, 11));
3464
+ ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16));
3656
3465
  ResultFormatter.position(
3657
3466
  decodeResult,
3658
3467
  CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
3659
- results.groups.unsplit_coords
3468
+ text.substring(30, 45).replace(/^(.)0/, "$1")
3660
3469
  )
3661
3470
  );
3662
- const flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? 0 : Number(results.groups.flight_level_or_ground);
3663
- ResultFormatter.month(
3664
- decodeResult,
3665
- Number(results.groups.current_date.substring(0, 2))
3666
- );
3667
- ResultFormatter.day(
3668
- decodeResult,
3669
- Number(results.groups.current_date.substring(2, 4))
3670
- );
3671
- ResultFormatter.time_of_day(
3471
+ ResultFormatter.altitude(
3672
3472
  decodeResult,
3673
- DateTimeUtils.convertHHMMSSToTod(results.groups.current_time + "00")
3473
+ Number(text.substring(48, 51)) * 100
3674
3474
  );
3675
- ResultFormatter.eta(
3475
+ ResultFormatter.unknownArr(
3676
3476
  decodeResult,
3677
- DateTimeUtils.convertHHMMSSToTod(results.groups.eta_time + "00")
3477
+ [text.substring(2, 4), text.substring(19, 29)],
3478
+ " "
3678
3479
  );
3679
- if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
3680
- decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
3480
+ } else if (fields.length === 33) {
3481
+ decodeResult.raw.date = fields[3];
3482
+ if (fields[1] === "B") {
3483
+ ResultFormatter.position(decodeResult, {
3484
+ latitude: Number(fields[4]),
3485
+ longitude: Number(fields[5])
3486
+ });
3487
+ ResultFormatter.altitude(decodeResult, Number(fields[6]));
3681
3488
  }
3682
- ResultFormatter.departureAirport(
3489
+ ResultFormatter.departureAirport(decodeResult, fields[8]);
3490
+ ResultFormatter.arrivalAirport(decodeResult, fields[9]);
3491
+ ResultFormatter.alternateAirport(decodeResult, fields[10]);
3492
+ ResultFormatter.arrivalRunway(decodeResult, fields[11].split("/")[0]);
3493
+ if (fields[12].length > 1) {
3494
+ ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
3495
+ }
3496
+ ResultFormatter.checksum(decodeResult, parseInt(fields[32], 16));
3497
+ ResultFormatter.unknownArr(
3683
3498
  decodeResult,
3684
- results.groups.departure_icao
3499
+ [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter(
3500
+ (f) => f != ""
3501
+ )
3685
3502
  );
3686
- ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
3687
- ResultFormatter.altitude(decodeResult, flight_level * 100);
3503
+ } else {
3504
+ decodeResult.decoded = false;
3505
+ ResultFormatter.unknown(decodeResult, text);
3506
+ }
3507
+ if (decodeResult.decoded) {
3508
+ if (!decodeResult.remaining.text)
3509
+ decodeResult.decoder.decodeLevel = "full";
3510
+ else decodeResult.decoder.decodeLevel = "partial";
3511
+ } else {
3512
+ decodeResult.decoder.decodeLevel = "none";
3688
3513
  }
3689
- decodeResult.decoded = true;
3690
- decodeResult.decoder.decodeLevel = "full";
3691
3514
  return decodeResult;
3692
3515
  }
3693
3516
  };
3694
3517
 
3695
- // lib/plugins/Label_44_Slash.ts
3696
- var Label_44_Slash = class extends DecoderPlugin {
3697
- name = "label-44-slash";
3518
+ // lib/plugins/Label_4T_AGFSR.ts
3519
+ var Label_4T_AGFSR = class extends DecoderPlugin {
3520
+ name = "label-4t-agfsr";
3698
3521
  qualifiers() {
3699
3522
  return {
3700
- labels: ["44"],
3701
- preambles: [" /FB"]
3523
+ labels: ["4T"],
3524
+ preambles: ["AGFSR"]
3702
3525
  };
3703
3526
  }
3704
3527
  decode(message, options = {}) {
3705
3528
  const decodeResult = this.defaultResult();
3706
3529
  decodeResult.decoder.name = this.name;
3707
- decodeResult.formatted.description = "Flight Briefing";
3530
+ decodeResult.formatted.description = "Position Report";
3708
3531
  decodeResult.message = message;
3709
- const fields = message.text.split("/");
3710
- if (fields.length !== 4) {
3532
+ const data = message.text.substring(5).split("/");
3533
+ if (!message.text.startsWith("AGFSR") || data.length !== 20) {
3711
3534
  if (options.debug) {
3712
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3535
+ console.log(`Decoder: Unknown 4T message: ${message.text}`);
3713
3536
  }
3714
3537
  ResultFormatter.unknown(decodeResult, message.text);
3715
3538
  decodeResult.decoded = false;
3716
3539
  decodeResult.decoder.decodeLevel = "none";
3717
3540
  return decodeResult;
3718
3541
  }
3719
- ResultFormatter.unknownArr(decodeResult, fields.slice(0, 2), "/");
3720
- const data = fields[3].split(",");
3721
- if (data.length >= 6) {
3722
- if (options.debug) {
3723
- console.log("Label 44 Slash: groups");
3724
- console.log(data);
3725
- }
3726
- ResultFormatter.position(decodeResult, {
3727
- latitude: (data[0].charAt(0) === "S" ? -1 : 1) * parseFloat(data[0].slice(1).trim()),
3728
- longitude: (data[1].charAt(0) === "W" ? -1 : 1) * parseFloat(data[1].slice(1).trim())
3729
- });
3730
- ResultFormatter.flightNumber(decodeResult, data[2]);
3731
- ResultFormatter.unknown(decodeResult, data[3]);
3732
- ResultFormatter.arrivalAirport(decodeResult, data[4]);
3733
- ResultFormatter.eta(
3542
+ ResultFormatter.flightNumber(decodeResult, data[0].trim());
3543
+ ResultFormatter.departureDay(decodeResult, Number(data[1]));
3544
+ ResultFormatter.arrivalDay(decodeResult, Number(data[2]));
3545
+ ResultFormatter.departureAirport(
3546
+ decodeResult,
3547
+ data[3].substring(0, 3),
3548
+ "IATA"
3549
+ );
3550
+ ResultFormatter.arrivalAirport(decodeResult, data[3].substring(3), "IATA");
3551
+ ResultFormatter.time_of_day(
3552
+ decodeResult,
3553
+ DateTimeUtils.convertHHMMSSToTod(data[4].substring(0, 4))
3554
+ );
3555
+ ResultFormatter.unknown(decodeResult, data[5], "/");
3556
+ const lat = data[6].substring(0, 7);
3557
+ const lon = data[6].substring(7, 15);
3558
+ ResultFormatter.position(decodeResult, {
3559
+ latitude: CoordinateUtils.getDirection(lat[6]) * Number(lat.substring(0, 2)) + Number(lat.substring(2, 6)) / 60,
3560
+ longitude: CoordinateUtils.getDirection(lon[7]) * Number(lon.substring(0, 3)) + Number(lon.substring(3, 7)) / 60
3561
+ });
3562
+ ResultFormatter.altitude(decodeResult, 100 * Number(data[7]));
3563
+ ResultFormatter.unknownArr(decodeResult, data.slice(8), "/");
3564
+ decodeResult.decoded = true;
3565
+ decodeResult.decoder.decodeLevel = "partial";
3566
+ return decodeResult;
3567
+ }
3568
+ };
3569
+
3570
+ // lib/plugins/Label_58.ts
3571
+ var Label_58 = class extends DecoderPlugin {
3572
+ name = "label-58";
3573
+ qualifiers() {
3574
+ return {
3575
+ labels: ["58"]
3576
+ };
3577
+ }
3578
+ decode(message, options = {}) {
3579
+ const decodeResult = this.defaultResult();
3580
+ decodeResult.decoder.name = this.name;
3581
+ decodeResult.formatted.description = "Position Report";
3582
+ decodeResult.message = message;
3583
+ const data = message.text.split("/");
3584
+ if (data.length === 8) {
3585
+ ResultFormatter.flightNumber(decodeResult, data[0]);
3586
+ ResultFormatter.day(decodeResult, Number(data[1]));
3587
+ ResultFormatter.time_of_day(
3734
3588
  decodeResult,
3735
- DateTimeUtils.convertHHMMSSToTod(data[5])
3589
+ DateTimeUtils.convertHHMMSSToTod(data[2])
3736
3590
  );
3737
- if (data.length === 18) {
3738
- ResultFormatter.unknownArr(decodeResult, data.slice(6, 8), ",");
3739
- ResultFormatter.remainingFuel(decodeResult, parseFloat(data[8]));
3740
- ResultFormatter.unknownArr(decodeResult, data.slice(9, 11), ",");
3741
- ResultFormatter.arrivalRunway(decodeResult, data[11]);
3742
- FlightPlanUtils.addProcedure(decodeResult, data[12], "arrival");
3743
- ResultFormatter.unknownArr(decodeResult, data.slice(13, 18), ",");
3744
- }
3591
+ const lat = data[3];
3592
+ const lon = data[4];
3593
+ ResultFormatter.position(decodeResult, {
3594
+ latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
3595
+ longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
3596
+ });
3597
+ ResultFormatter.altitude(decodeResult, Number(data[5]));
3598
+ ResultFormatter.unknown(decodeResult, data[6], "/");
3599
+ ResultFormatter.unknown(decodeResult, data[7], "/");
3745
3600
  } else {
3746
3601
  if (options.debug) {
3747
- console.log(`Decoder: Unknown 44 message: ${message.text}`);
3602
+ console.log(`Decoder: Unknown 58 message: ${message.text}`);
3748
3603
  }
3749
3604
  ResultFormatter.unknown(decodeResult, message.text);
3750
3605
  decodeResult.decoded = false;
@@ -3757,276 +3612,227 @@ var Label_44_Slash = class extends DecoderPlugin {
3757
3612
  }
3758
3613
  };
3759
3614
 
3760
- // lib/plugins/Label_4A.ts
3761
- var Label_4A = class extends DecoderPlugin {
3762
- name = "label-4a";
3615
+ // lib/plugins/Label_4T_ETA.ts
3616
+ var Label_4T_ETA = class extends DecoderPlugin {
3617
+ name = "label-4t-eta";
3763
3618
  qualifiers() {
3764
3619
  return {
3765
- labels: ["4A"]
3620
+ labels: ["4T"],
3621
+ preambles: ["ETA"]
3766
3622
  };
3767
3623
  }
3768
3624
  decode(message, options = {}) {
3769
3625
  const decodeResult = this.defaultResult();
3770
3626
  decodeResult.decoder.name = this.name;
3627
+ decodeResult.formatted.description = "ETA Report";
3771
3628
  decodeResult.message = message;
3772
- decodeResult.formatted.description = "Latest New Format";
3629
+ const data = message.text.substring(3).split("/");
3630
+ if (!message.text.startsWith("ETA") || data.length !== 3) {
3631
+ if (options.debug) {
3632
+ console.log(`Decoder: Unknown 4T message: ${message.text}`);
3633
+ }
3634
+ ResultFormatter.unknown(decodeResult, message.text);
3635
+ decodeResult.decoded = false;
3636
+ decodeResult.decoder.decodeLevel = "none";
3637
+ return decodeResult;
3638
+ }
3639
+ ResultFormatter.flightNumber(decodeResult, data[0].trim());
3640
+ ResultFormatter.departureDay(decodeResult, Number(data[1]));
3641
+ const etaData = data[2].split(" ");
3642
+ ResultFormatter.arrivalDay(decodeResult, Number(etaData[0]));
3643
+ ResultFormatter.arrivalAirport(decodeResult, etaData[1], "IATA");
3644
+ ResultFormatter.eta(
3645
+ decodeResult,
3646
+ DateTimeUtils.convertHHMMSSToTod(etaData[2].substring(0, 4))
3647
+ );
3773
3648
  decodeResult.decoded = true;
3774
- const fields = message.text.split(",");
3775
- if (fields.length === 11) {
3776
- ResultFormatter.time_of_day(
3777
- decodeResult,
3778
- DateTimeUtils.convertHHMMSSToTod(fields[0])
3779
- );
3780
- ResultFormatter.tail(decodeResult, fields[2].replace(".", ""));
3781
- if (fields[3]) ResultFormatter.callsign(decodeResult, fields[3]);
3782
- ResultFormatter.departureAirport(decodeResult, fields[4]);
3783
- ResultFormatter.arrivalAirport(decodeResult, fields[5]);
3784
- ResultFormatter.unknownArr(decodeResult, fields.slice(8));
3785
- } else if (fields.length === 6) {
3786
- if (fields[0].match(/^[NS]/)) {
3787
- ResultFormatter.position(
3788
- decodeResult,
3789
- CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13))
3790
- );
3791
- let wp1 = {
3792
- name: fields[0].substring(13).trim(),
3793
- time: DateTimeUtils.convertHHMMSSToTod(fields[1].substring(0, 6)),
3794
- timeFormat: "tod"
3795
- };
3796
- ResultFormatter.altitude(
3797
- decodeResult,
3798
- Number(fields[1].substring(6, 9)) * 100
3799
- );
3800
- let wp2 = {
3801
- name: fields[1].substring(9).trim(),
3802
- time: DateTimeUtils.convertHHMMSSToTod(fields[2]),
3803
- timeFormat: "tod"
3804
- };
3805
- ResultFormatter.route(decodeResult, { waypoints: [wp1, wp2] });
3806
- ResultFormatter.temperature(decodeResult, fields[3]);
3807
- ResultFormatter.unknownArr(decodeResult, fields.slice(4));
3808
- } else {
3809
- ResultFormatter.time_of_day(
3810
- decodeResult,
3811
- DateTimeUtils.convertHHMMSSToTod(fields[0])
3812
- );
3813
- ResultFormatter.eta(
3814
- decodeResult,
3815
- DateTimeUtils.convertHHMMSSToTod(fields[1])
3816
- );
3817
- ResultFormatter.unknown(decodeResult, fields[2]);
3818
- ResultFormatter.altitude(decodeResult, Number(fields[3]));
3819
- ResultFormatter.position(
3820
- decodeResult,
3821
- CoordinateUtils.decodeStringCoordinates(
3822
- (fields[4] + fields[5]).replace(/[ \.]/g, "")
3823
- )
3824
- );
3825
- }
3826
- } else {
3827
- decodeResult.decoded = false;
3828
- ResultFormatter.unknown(decodeResult, message.text);
3829
- }
3830
- if (decodeResult.decoded) {
3831
- if (!decodeResult.remaining.text)
3832
- decodeResult.decoder.decodeLevel = "full";
3833
- else decodeResult.decoder.decodeLevel = "partial";
3834
- } else {
3835
- decodeResult.decoder.decodeLevel = "none";
3836
- }
3649
+ decodeResult.decoder.decodeLevel = "full";
3837
3650
  return decodeResult;
3838
3651
  }
3839
3652
  };
3840
3653
 
3841
- // lib/plugins/Label_4A_01.ts
3842
- var Label_4A_01 = class extends DecoderPlugin {
3843
- name = "label-4a-01";
3654
+ // lib/plugins/Label_80.ts
3655
+ var Label_80 = class extends DecoderPlugin {
3656
+ name = "label-80";
3844
3657
  qualifiers() {
3845
3658
  return {
3846
- labels: ["4A"],
3847
- preambles: ["01"]
3659
+ labels: ["80"],
3660
+ preambles: []
3848
3661
  };
3849
3662
  }
3850
3663
  decode(message, options = {}) {
3851
3664
  const decodeResult = this.defaultResult();
3852
3665
  decodeResult.decoder.name = this.name;
3853
- decodeResult.message = message;
3854
- decodeResult.formatted.description = "Latest New Format";
3855
- decodeResult.decoded = true;
3856
- let rgx = message.text.match(
3857
- /^01([A-Z]{2})([A-Z]{2})\s*(\w+)\/(\d{6})([A-Z]{4})([A-Z]{4})\r\n([+-]\s*\d+)(\d{3}\.\d)([+-]\s*\d+\.\d)/
3858
- );
3859
- if (rgx) {
3860
- ResultFormatter.state_change(decodeResult, rgx[1], rgx[2]);
3861
- ResultFormatter.callsign(decodeResult, rgx[3]);
3862
- ResultFormatter.time_of_day(
3863
- decodeResult,
3864
- DateTimeUtils.convertHHMMSSToTod(rgx[4] + "00")
3865
- );
3866
- ResultFormatter.departureAirport(decodeResult, rgx[5]);
3867
- ResultFormatter.arrivalAirport(decodeResult, rgx[6]);
3868
- ResultFormatter.altitude(decodeResult, Number(rgx[7].replace(/ /g, "")));
3869
- ResultFormatter.unknown(decodeResult, rgx[8]);
3870
- ResultFormatter.temperature(decodeResult, rgx[9].replace(/ /g, ""));
3666
+ decodeResult.formatted.description = "Airline Defined Position Report";
3667
+ const lines = message.text.split(/\r?\n/);
3668
+ if (lines.length === 1 && lines[0].includes(",")) {
3669
+ this.parseCsvFormat(lines[0], decodeResult);
3871
3670
  } else {
3872
- decodeResult.decoded = false;
3873
- ResultFormatter.unknown(decodeResult, message.text);
3671
+ const header = lines[0].trim();
3672
+ const headerParts = header.split(",");
3673
+ for (let i = 0; i < headerParts.length - 1; i++) {
3674
+ const moreFields = headerParts[i].split("/");
3675
+ for (const more of moreFields) {
3676
+ this.parseTags(more.trim(), decodeResult);
3677
+ }
3678
+ }
3679
+ this.parseHeader(
3680
+ headerParts[headerParts.length - 1].trim(),
3681
+ decodeResult
3682
+ );
3683
+ for (let i = 1; i < lines.length; i++) {
3684
+ const line = lines[i];
3685
+ const parts = line.split("/");
3686
+ for (const part of parts) {
3687
+ this.parseTags(part.trim(), decodeResult);
3688
+ }
3689
+ }
3874
3690
  }
3875
- if (decodeResult.decoded) {
3876
- if (!decodeResult.remaining.text)
3877
- decodeResult.decoder.decodeLevel = "full";
3878
- else decodeResult.decoder.decodeLevel = "partial";
3879
- } else {
3880
- decodeResult.decoder.decodeLevel = "none";
3691
+ if (decodeResult.formatted.items.length > 0) {
3692
+ decodeResult.decoded = true;
3693
+ decodeResult.decoder.decodeLevel = decodeResult.remaining.text === void 0 ? "full" : "partial";
3881
3694
  }
3882
3695
  return decodeResult;
3883
3696
  }
3884
- };
3885
-
3886
- // lib/plugins/Label_4A_DIS.ts
3887
- var Label_4A_DIS = class extends DecoderPlugin {
3888
- name = "label-4a-dis";
3889
- qualifiers() {
3890
- return {
3891
- labels: ["4A"],
3892
- preambles: ["DIS"]
3893
- };
3894
- }
3895
- decode(message, options = {}) {
3896
- const decodeResult = this.defaultResult();
3897
- decodeResult.decoder.name = this.name;
3898
- decodeResult.message = message;
3899
- decodeResult.formatted.description = "Latest New Format";
3900
- decodeResult.decoded = true;
3901
- const fields = message.text.split(",");
3902
- ResultFormatter.time_of_day(
3903
- decodeResult,
3904
- DateTimeUtils.convertHHMMSSToTod(fields[1].substring(2) + "00")
3905
- );
3906
- ResultFormatter.callsign(decodeResult, fields[2]);
3907
- ResultFormatter.freetext(decodeResult, fields.slice(3).join(""));
3908
- if (decodeResult.decoded) {
3909
- if (!decodeResult.remaining.text)
3910
- decodeResult.decoder.decodeLevel = "full";
3911
- else decodeResult.decoder.decodeLevel = "partial";
3912
- } else {
3913
- decodeResult.decoder.decodeLevel = "none";
3697
+ parseHeader(header, results) {
3698
+ const fields = header.split("/");
3699
+ if (fields.length < 3) {
3700
+ ResultFormatter.unknown(results, header, "/");
3701
+ return;
3914
3702
  }
3915
- return decodeResult;
3916
- }
3917
- };
3918
-
3919
- // lib/plugins/Label_4A_DOOR.ts
3920
- var Label_4A_DOOR = class extends DecoderPlugin {
3921
- name = "label-4a-door";
3922
- qualifiers() {
3923
- return {
3924
- labels: ["4A"],
3925
- preambles: ["DOOR"]
3926
- };
3927
- }
3928
- decode(message, options = {}) {
3929
- const decodeResult = this.defaultResult();
3930
- decodeResult.decoder.name = this.name;
3931
- decodeResult.message = message;
3932
- decodeResult.formatted.description = "Latest New Format";
3933
- decodeResult.decoded = true;
3934
- const fields = message.text.split(" ");
3935
- if (fields.length === 3) {
3936
- ResultFormatter.door_event(
3937
- decodeResult,
3938
- fields[0].split("/")[1],
3939
- fields[1]
3940
- );
3941
- ResultFormatter.time_of_day(
3942
- decodeResult,
3943
- DateTimeUtils.convertHHMMSSToTod(fields[2] + "00")
3944
- );
3703
+ const msgInfo = fields[0].split(/\s+/);
3704
+ if (msgInfo.length === 3) {
3705
+ ResultFormatter.unknownArr(results, msgInfo.slice(0, 2), " ");
3706
+ ResultFormatter.flightNumber(results, msgInfo[2]);
3945
3707
  } else {
3946
- decodeResult.decoded = false;
3947
- ResultFormatter.unknown(decodeResult, message.text);
3708
+ ResultFormatter.unknown(results, header, "/");
3709
+ return;
3948
3710
  }
3949
- if (decodeResult.decoded) {
3950
- if (!decodeResult.remaining.text)
3951
- decodeResult.decoder.decodeLevel = "full";
3952
- else decodeResult.decoder.decodeLevel = "partial";
3711
+ const otherInfo1 = fields[1].split(/\s+/);
3712
+ if (otherInfo1.length === 2) {
3713
+ ResultFormatter.day(results, parseInt(otherInfo1[0], 10));
3714
+ ResultFormatter.departureAirport(results, otherInfo1[1]);
3953
3715
  } else {
3954
- decodeResult.decoder.decodeLevel = "none";
3716
+ ResultFormatter.unknownArr(results, otherInfo1, " ");
3955
3717
  }
3956
- return decodeResult;
3957
- }
3958
- };
3959
-
3960
- // lib/plugins/Label_4A_Slash_01.ts
3961
- var Label_4A_Slash_01 = class extends DecoderPlugin {
3962
- name = "label-4a-slash-01";
3963
- qualifiers() {
3964
- return {
3965
- labels: ["4A"],
3966
- preambles: ["/01"]
3967
- };
3968
- }
3969
- decode(message, options = {}) {
3970
- const decodeResult = this.defaultResult();
3971
- decodeResult.decoder.name = this.name;
3972
- decodeResult.message = message;
3973
- decodeResult.formatted.description = "Latest New Format";
3974
- decodeResult.decoded = true;
3975
- if (message.text.length === 5 && message.text.substring(0, 4) === "/01-") {
3976
- ResultFormatter.unknown(decodeResult, message.text.substring(4));
3718
+ const otherInfo2 = fields[2].split(/\s+/);
3719
+ if (otherInfo2.length === 2) {
3720
+ ResultFormatter.arrivalAirport(results, otherInfo2[0]);
3721
+ ResultFormatter.tail(results, otherInfo2[1].replace(".", ""));
3977
3722
  } else {
3978
- decodeResult.decoded = false;
3979
- ResultFormatter.unknown(decodeResult, message.text);
3723
+ ResultFormatter.unknownArr(results, otherInfo2, " ");
3980
3724
  }
3981
- if (decodeResult.decoded) {
3982
- if (!decodeResult.remaining.text)
3983
- decodeResult.decoder.decodeLevel = "full";
3984
- else decodeResult.decoder.decodeLevel = "partial";
3985
- } else {
3986
- decodeResult.decoder.decodeLevel = "none";
3725
+ if (fields.length > 3) {
3726
+ ResultFormatter.unknownArr(results, fields.slice(3), "/");
3987
3727
  }
3988
- return decodeResult;
3989
- }
3990
- };
3991
-
3992
- // lib/plugins/Label_4J_POS.ts
3993
- var Label_4J_POS = class extends DecoderPlugin {
3994
- name = "label-4j-pos";
3995
- qualifiers() {
3996
- return {
3997
- labels: ["4J"],
3998
- preambles: ["POS/"]
3999
- };
4000
3728
  }
4001
- // copied from Label_H1.ts since i don't really want to have to have
4002
- // something named like that decode more than 1 type
4003
- // if we figure out a good name, i'll combine them
4004
- decode(message, options = {}) {
4005
- let decodeResult = this.defaultResult();
4006
- decodeResult.decoder.name = this.name;
4007
- decodeResult.message = message;
4008
- const msg = message.text.replace(/\n|\r/g, "");
4009
- const decoded = H1Helper.decodeH1Message(decodeResult, msg);
4010
- decodeResult.decoded = decoded;
4011
- decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
4012
- if (decodeResult.formatted.items.length === 0) {
4013
- if (options.debug) {
4014
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
4015
- }
4016
- ResultFormatter.unknown(decodeResult, message.text);
4017
- decodeResult.decoded = false;
4018
- decodeResult.decoder.decodeLevel = "none";
3729
+ parseTags(part, results) {
3730
+ const kvPair = part.split(/\s+/);
3731
+ if (kvPair.length < 2) {
3732
+ ResultFormatter.unknown(results, part, "/");
3733
+ return;
4019
3734
  }
4020
- return decodeResult;
3735
+ const tag = kvPair[0];
3736
+ const val = kvPair.slice(1).join(" ");
3737
+ switch (tag) {
3738
+ case "POS":
3739
+ const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
3740
+ const posResult = val.match(posRegex);
3741
+ const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.latd === "S" ? -1 : 1);
3742
+ const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
3743
+ const position = {
3744
+ latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
3745
+ longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
3746
+ };
3747
+ ResultFormatter.position(results, position);
3748
+ break;
3749
+ case "ALT":
3750
+ ResultFormatter.altitude(results, parseInt(val.replace("+", ""), 10));
3751
+ break;
3752
+ case "FL":
3753
+ ResultFormatter.altitude(results, parseInt(val, 10) * 100);
3754
+ break;
3755
+ case "MCH":
3756
+ ResultFormatter.mach(results, parseInt(val, 10) / 1e3);
3757
+ break;
3758
+ case "SPD":
3759
+ ResultFormatter.groundspeed(results, parseInt(val, 10));
3760
+ break;
3761
+ case "TAS":
3762
+ ResultFormatter.airspeed(results, parseInt(val, 10));
3763
+ break;
3764
+ case "SAT":
3765
+ ResultFormatter.temperature(results, val);
3766
+ break;
3767
+ case "FB":
3768
+ break;
3769
+ case "FOB":
3770
+ ResultFormatter.currentFuel(
3771
+ results,
3772
+ parseInt(val.replace(/\D/g, ""), 10)
3773
+ );
3774
+ break;
3775
+ case "UTC":
3776
+ ResultFormatter.time_of_day(
3777
+ results,
3778
+ DateTimeUtils.convertHHMMSSToTod(val)
3779
+ );
3780
+ break;
3781
+ case "ETA":
3782
+ const hhmm = val.split(".")[0].replace(":", "");
3783
+ ResultFormatter.eta(results, DateTimeUtils.convertHHMMSSToTod(hhmm));
3784
+ break;
3785
+ case "HDG":
3786
+ ResultFormatter.heading(results, parseInt(val, 10));
3787
+ break;
3788
+ case "NWYP":
3789
+ results.raw.next_waypoint = val;
3790
+ break;
3791
+ case "SWN":
3792
+ ResultFormatter.unknown(results, part, "/");
3793
+ break;
3794
+ case "DWN":
3795
+ ResultFormatter.unknown(results, part, "/");
3796
+ break;
3797
+ case "AD":
3798
+ break;
3799
+ default:
3800
+ ResultFormatter.unknown(results, part, "/");
3801
+ }
3802
+ }
3803
+ parseCsvFormat(text, results) {
3804
+ const csvParts = text.split(",");
3805
+ if (csvParts.length !== 9) {
3806
+ return;
3807
+ }
3808
+ const header = csvParts[0].trim().split(/\s+/);
3809
+ ResultFormatter.unknown(results, header[0], " ");
3810
+ ResultFormatter.unknown(results, header[1], " ");
3811
+ ResultFormatter.position(
3812
+ results,
3813
+ CoordinateUtils.decodeStringCoordinates(header[2])
3814
+ );
3815
+ ResultFormatter.unknown(results, csvParts[1]);
3816
+ ResultFormatter.time_of_day(
3817
+ results,
3818
+ DateTimeUtils.convertHHMMSSToTod(csvParts[2])
3819
+ );
3820
+ ResultFormatter.unknownArr(results, csvParts.slice(4, 6), ",");
3821
+ ResultFormatter.temperature(
3822
+ results,
3823
+ ((csvParts[6].charAt(0) === "M" ? -1 : 1) * parseInt(csvParts[6].slice(1), 10)).toString()
3824
+ );
3825
+ ResultFormatter.airspeed(results, parseInt(csvParts[7], 10));
3826
+ ResultFormatter.currentFuel(results, parseInt(csvParts[8], 10));
4021
3827
  }
4022
3828
  };
4023
3829
 
4024
- // lib/plugins/Label_4N.ts
4025
- var Label_4N = class extends DecoderPlugin {
4026
- name = "label-4n";
3830
+ // lib/plugins/Label_83.ts
3831
+ var Label_83 = class extends DecoderPlugin {
3832
+ name = "label-83";
4027
3833
  qualifiers() {
4028
3834
  return {
4029
- labels: ["4N"]
3835
+ labels: ["83"]
4030
3836
  };
4031
3837
  }
4032
3838
  decode(message, options = {}) {
@@ -4036,52 +3842,49 @@ var Label_4N = class extends DecoderPlugin {
4036
3842
  decodeResult.formatted.description = "Airline Defined";
4037
3843
  decodeResult.decoded = true;
4038
3844
  const text = message.text;
4039
- const fields = text.split(",");
4040
- if (text.length === 51) {
4041
- decodeResult.raw.day = text.substring(0, 2);
4042
- ResultFormatter.departureAirport(decodeResult, text.substring(8, 11));
4043
- ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16));
4044
- ResultFormatter.position(
4045
- decodeResult,
4046
- CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
4047
- text.substring(30, 45).replace(/^(.)0/, "$1")
4048
- )
4049
- );
4050
- ResultFormatter.altitude(
3845
+ if (text.substring(0, 10) === "4DH3 ETAT2") {
3846
+ const fields = text.split(/\s+/);
3847
+ if (fields[2].length > 5) {
3848
+ decodeResult.raw.day = fields[2].substring(5);
3849
+ }
3850
+ ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
3851
+ const subfields = fields[3].split("/");
3852
+ ResultFormatter.departureAirport(decodeResult, subfields[0]);
3853
+ ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
3854
+ ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
3855
+ ResultFormatter.eta(
4051
3856
  decodeResult,
4052
- Number(text.substring(48, 51)) * 100
3857
+ DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")
4053
3858
  );
4054
- ResultFormatter.unknownArr(
4055
- decodeResult,
4056
- [text.substring(2, 4), text.substring(19, 29)],
4057
- " "
3859
+ } else if (text.substring(0, 5) === "001PR") {
3860
+ decodeResult.raw.day = text.substring(5, 7);
3861
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
3862
+ text.substring(13, 28).replace(/\./g, "")
4058
3863
  );
4059
- } else if (fields.length === 33) {
4060
- decodeResult.raw.date = fields[3];
4061
- if (fields[1] === "B") {
3864
+ if (position) {
3865
+ ResultFormatter.position(decodeResult, position);
3866
+ }
3867
+ ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
3868
+ ResultFormatter.unknown(decodeResult, text.substring(33));
3869
+ } else {
3870
+ const fields = text.replace(/\s/g, "").split(",");
3871
+ if (fields.length === 9) {
3872
+ ResultFormatter.departureAirport(decodeResult, fields[0]);
3873
+ ResultFormatter.arrivalAirport(decodeResult, fields[1]);
3874
+ decodeResult.raw.day = fields[2].substring(0, 2);
3875
+ decodeResult.raw.time = fields[2].substring(2);
4062
3876
  ResultFormatter.position(decodeResult, {
4063
- latitude: Number(fields[4]),
4064
- longitude: Number(fields[5])
3877
+ latitude: Number(fields[3].replace(/\s/g, "")),
3878
+ longitude: Number(fields[4].replace(/\s/g, ""))
4065
3879
  });
4066
- ResultFormatter.altitude(decodeResult, Number(fields[6]));
4067
- }
4068
- ResultFormatter.departureAirport(decodeResult, fields[8]);
4069
- ResultFormatter.arrivalAirport(decodeResult, fields[9]);
4070
- ResultFormatter.alternateAirport(decodeResult, fields[10]);
4071
- ResultFormatter.arrivalRunway(decodeResult, fields[11].split("/")[0]);
4072
- if (fields[12].length > 1) {
4073
- ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
3880
+ ResultFormatter.altitude(decodeResult, Number(fields[5]));
3881
+ ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
3882
+ ResultFormatter.heading(decodeResult, Number(fields[7]));
3883
+ ResultFormatter.unknown(decodeResult, fields[8]);
3884
+ } else {
3885
+ decodeResult.decoded = false;
3886
+ ResultFormatter.unknown(decodeResult, text);
4074
3887
  }
4075
- ResultFormatter.checksum(decodeResult, parseInt(fields[32], 16));
4076
- ResultFormatter.unknownArr(
4077
- decodeResult,
4078
- [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter(
4079
- (f) => f != ""
4080
- )
4081
- );
4082
- } else {
4083
- decodeResult.decoded = false;
4084
- ResultFormatter.unknown(decodeResult, text);
4085
3888
  }
4086
3889
  if (decodeResult.decoded) {
4087
3890
  if (!decodeResult.remaining.text)
@@ -4094,469 +3897,569 @@ var Label_4N = class extends DecoderPlugin {
4094
3897
  }
4095
3898
  };
4096
3899
 
4097
- // lib/plugins/Label_4T_AGFSR.ts
4098
- var Label_4T_AGFSR = class extends DecoderPlugin {
4099
- name = "label-4t-agfsr";
3900
+ // lib/plugins/Label_8E.ts
3901
+ var Label_8E = class extends DecoderPlugin {
3902
+ name = "label-8e";
4100
3903
  qualifiers() {
4101
3904
  return {
4102
- labels: ["4T"],
4103
- preambles: ["AGFSR"]
3905
+ labels: ["8E"]
4104
3906
  };
4105
3907
  }
4106
3908
  decode(message, options = {}) {
4107
3909
  const decodeResult = this.defaultResult();
4108
3910
  decodeResult.decoder.name = this.name;
4109
- decodeResult.formatted.description = "Position Report";
3911
+ decodeResult.formatted.description = "ETA Report";
4110
3912
  decodeResult.message = message;
4111
- const data = message.text.substring(5).split("/");
4112
- if (!message.text.startsWith("AGFSR") || data.length !== 20) {
3913
+ const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
3914
+ const results = message.text.match(regex);
3915
+ if (results?.groups) {
4113
3916
  if (options.debug) {
4114
- console.log(`Decoder: Unknown 4T message: ${message.text}`);
3917
+ console.log("Label 8E ETA: groups");
3918
+ console.log(results.groups);
4115
3919
  }
4116
- ResultFormatter.unknown(decodeResult, message.text);
4117
- decodeResult.decoded = false;
4118
- decodeResult.decoder.decodeLevel = "none";
4119
- return decodeResult;
3920
+ ResultFormatter.eta(
3921
+ decodeResult,
3922
+ DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta)
3923
+ );
3924
+ ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
4120
3925
  }
4121
- ResultFormatter.flightNumber(decodeResult, data[0].trim());
4122
- ResultFormatter.departureDay(decodeResult, Number(data[1]));
4123
- ResultFormatter.arrivalDay(decodeResult, Number(data[2]));
4124
- ResultFormatter.departureAirport(
4125
- decodeResult,
4126
- data[3].substring(0, 3),
4127
- "IATA"
4128
- );
4129
- ResultFormatter.arrivalAirport(decodeResult, data[3].substring(3), "IATA");
4130
- ResultFormatter.time_of_day(
4131
- decodeResult,
4132
- DateTimeUtils.convertHHMMSSToTod(data[4].substring(0, 4))
4133
- );
4134
- ResultFormatter.unknown(decodeResult, data[5], "/");
4135
- const lat = data[6].substring(0, 7);
4136
- const lon = data[6].substring(7, 15);
4137
- ResultFormatter.position(decodeResult, {
4138
- latitude: CoordinateUtils.getDirection(lat[6]) * Number(lat.substring(0, 2)) + Number(lat.substring(2, 6)) / 60,
4139
- longitude: CoordinateUtils.getDirection(lon[7]) * Number(lon.substring(0, 3)) + Number(lon.substring(3, 7)) / 60
4140
- });
4141
- ResultFormatter.altitude(decodeResult, 100 * Number(data[7]));
4142
- ResultFormatter.unknownArr(decodeResult, data.slice(8), "/");
4143
3926
  decodeResult.decoded = true;
4144
- decodeResult.decoder.decodeLevel = "partial";
3927
+ decodeResult.decoder.decodeLevel = "full";
4145
3928
  return decodeResult;
4146
3929
  }
4147
3930
  };
4148
3931
 
4149
- // lib/plugins/Label_58.ts
4150
- var Label_58 = class extends DecoderPlugin {
4151
- name = "label-58";
3932
+ // lib/plugins/Label_B6.ts
3933
+ var Label_B6_Forwardslash = class extends DecoderPlugin {
3934
+ name = "label-b6-forwardslash";
4152
3935
  qualifiers() {
4153
3936
  return {
4154
- labels: ["58"]
3937
+ labels: ["B6"],
3938
+ preambles: ["/"]
4155
3939
  };
4156
3940
  }
4157
3941
  decode(message, options = {}) {
4158
3942
  const decodeResult = this.defaultResult();
4159
3943
  decodeResult.decoder.name = this.name;
4160
- decodeResult.formatted.description = "Position Report";
3944
+ decodeResult.formatted.description = "CPDLC Message";
4161
3945
  decodeResult.message = message;
4162
- const data = message.text.split("/");
4163
- if (data.length === 8) {
4164
- ResultFormatter.flightNumber(decodeResult, data[0]);
4165
- ResultFormatter.day(decodeResult, Number(data[1]));
4166
- ResultFormatter.time_of_day(
4167
- decodeResult,
4168
- DateTimeUtils.convertHHMMSSToTod(data[2])
4169
- );
4170
- const lat = data[3];
4171
- const lon = data[4];
4172
- ResultFormatter.position(decodeResult, {
4173
- latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
4174
- longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
4175
- });
4176
- ResultFormatter.altitude(decodeResult, Number(data[5]));
4177
- ResultFormatter.unknown(decodeResult, data[6], "/");
4178
- ResultFormatter.unknown(decodeResult, data[7], "/");
4179
- } else {
4180
- if (options.debug) {
4181
- console.log(`Decoder: Unknown 58 message: ${message.text}`);
4182
- }
4183
- ResultFormatter.unknown(decodeResult, message.text);
4184
- decodeResult.decoded = false;
4185
- decodeResult.decoder.decodeLevel = "none";
4186
- return decodeResult;
3946
+ if (options.debug) {
3947
+ console.log("CPDLC: " + message);
4187
3948
  }
4188
- decodeResult.decoded = true;
4189
- decodeResult.decoder.decodeLevel = "partial";
4190
3949
  return decodeResult;
4191
3950
  }
4192
3951
  };
4193
3952
 
4194
- // lib/plugins/Label_4T_ETA.ts
4195
- var Label_4T_ETA = class extends DecoderPlugin {
4196
- name = "label-4t-eta";
3953
+ // lib/plugins/Label_ColonComma.ts
3954
+ var Label_ColonComma = class extends DecoderPlugin {
3955
+ name = "label-colon-comma";
4197
3956
  qualifiers() {
4198
3957
  return {
4199
- labels: ["4T"],
4200
- preambles: ["ETA"]
3958
+ labels: [":;"]
4201
3959
  };
4202
3960
  }
4203
3961
  decode(message, options = {}) {
4204
3962
  const decodeResult = this.defaultResult();
4205
3963
  decodeResult.decoder.name = this.name;
4206
- decodeResult.formatted.description = "ETA Report";
4207
- decodeResult.message = message;
4208
- const data = message.text.substring(3).split("/");
4209
- if (!message.text.startsWith("ETA") || data.length !== 3) {
4210
- if (options.debug) {
4211
- console.log(`Decoder: Unknown 4T message: ${message.text}`);
4212
- }
4213
- ResultFormatter.unknown(decodeResult, message.text);
4214
- decodeResult.decoded = false;
4215
- decodeResult.decoder.decodeLevel = "none";
4216
- return decodeResult;
4217
- }
4218
- ResultFormatter.flightNumber(decodeResult, data[0].trim());
4219
- ResultFormatter.departureDay(decodeResult, Number(data[1]));
4220
- const etaData = data[2].split(" ");
4221
- ResultFormatter.arrivalDay(decodeResult, Number(etaData[0]));
4222
- ResultFormatter.arrivalAirport(decodeResult, etaData[1], "IATA");
4223
- ResultFormatter.eta(
4224
- decodeResult,
4225
- DateTimeUtils.convertHHMMSSToTod(etaData[2].substring(0, 4))
4226
- );
3964
+ decodeResult.raw.frequency = Number(message.text) / 1e3;
3965
+ decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
3966
+ decodeResult.formatted.items.push({
3967
+ type: "frequency",
3968
+ label: "Frequency",
3969
+ value: `${decodeResult.raw.frequency} MHz`,
3970
+ code: "FREQ"
3971
+ });
4227
3972
  decodeResult.decoded = true;
4228
3973
  decodeResult.decoder.decodeLevel = "full";
4229
3974
  return decodeResult;
4230
3975
  }
4231
3976
  };
4232
3977
 
4233
- // lib/plugins/Label_80.ts
4234
- var Label_80 = class extends DecoderPlugin {
4235
- name = "label-80";
4236
- qualifiers() {
4237
- return {
4238
- labels: ["80"],
4239
- preambles: []
4240
- };
4241
- }
4242
- decode(message, options = {}) {
4243
- const decodeResult = this.defaultResult();
4244
- decodeResult.decoder.name = this.name;
4245
- decodeResult.formatted.description = "Airline Defined Position Report";
4246
- const lines = message.text.split(/\r?\n/);
4247
- if (lines.length === 1 && lines[0].includes(",")) {
4248
- this.parseCsvFormat(lines[0], decodeResult);
3978
+ // lib/utils/h1_helper.ts
3979
+ var H1Helper = class _H1Helper {
3980
+ static decodeH1Message(decodeResult, message) {
3981
+ const checksum = parseInt(message.slice(-4), 16);
3982
+ const data = message.slice(0, message.length - 4);
3983
+ let checksumAlgorithmUsed = "";
3984
+ if (crc16IbmSdlcRev(data) === checksum) {
3985
+ checksumAlgorithmUsed = "IBM-SDLC reversed";
3986
+ } else if (crc16Genibus(data) === checksum) {
3987
+ checksumAlgorithmUsed = "GENIBUS";
4249
3988
  } else {
4250
- const header = lines[0].trim();
4251
- const headerParts = header.split(",");
4252
- for (let i = 0; i < headerParts.length - 1; i++) {
4253
- const moreFields = headerParts[i].split("/");
4254
- for (const more of moreFields) {
4255
- this.parseTags(more.trim(), decodeResult);
4256
- }
4257
- }
4258
- this.parseHeader(
4259
- headerParts[headerParts.length - 1].trim(),
4260
- decodeResult
4261
- );
4262
- for (let i = 1; i < lines.length; i++) {
4263
- const line = lines[i];
4264
- const parts = line.split("/");
4265
- for (const part of parts) {
4266
- this.parseTags(part.trim(), decodeResult);
4267
- }
4268
- }
3989
+ decodeResult.decoded = false;
3990
+ decodeResult.decoder.decodeLevel = "none";
3991
+ return false;
4269
3992
  }
4270
- if (decodeResult.formatted.items.length > 0) {
4271
- decodeResult.decoded = true;
4272
- decodeResult.decoder.decodeLevel = decodeResult.remaining.text === void 0 ? "full" : "partial";
3993
+ const fields = data.split("/");
3994
+ const canDecode = parseMessageType(decodeResult, fields[0]);
3995
+ if (!canDecode) {
3996
+ decodeResult.decoded = false;
3997
+ decodeResult.decoder.decodeLevel = "none";
3998
+ return false;
4273
3999
  }
4274
- return decodeResult;
4000
+ for (let i = 1; i < fields.length; ++i) {
4001
+ const key = fields[i].substring(0, 2);
4002
+ const data2 = fields[i].substring(2);
4003
+ switch (key) {
4004
+ case "AF":
4005
+ processAirField(decodeResult, data2.split(","));
4006
+ break;
4007
+ case "AK":
4008
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
4009
+ break;
4010
+ case "CG":
4011
+ processCenterOfGravity(decodeResult, data2.split(","));
4012
+ break;
4013
+ case "DC":
4014
+ processDateCode(decodeResult, data2.split(","));
4015
+ break;
4016
+ case "DI":
4017
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
4018
+ break;
4019
+ case "DT":
4020
+ processDT(decodeResult, data2.split(","));
4021
+ break;
4022
+ case "DQ":
4023
+ ResultFormatter.desiredAltitude(
4024
+ decodeResult,
4025
+ parseInt(data2, 10) * 100
4026
+ );
4027
+ break;
4028
+ case "ET":
4029
+ processETA(data2, decodeResult, fields, i);
4030
+ break;
4031
+ case "FB":
4032
+ ResultFormatter.currentFuel(decodeResult, parseInt(data2, 10));
4033
+ break;
4034
+ case "FN":
4035
+ decodeResult.raw.flight_number = data2;
4036
+ break;
4037
+ case "FX":
4038
+ ResultFormatter.freetext(decodeResult, data2);
4039
+ break;
4040
+ case "GA":
4041
+ ResultFormatter.groundAddress(decodeResult, data2);
4042
+ break;
4043
+ case "ID":
4044
+ processIdentification(decodeResult, data2.split(","));
4045
+ break;
4046
+ case "LR":
4047
+ processLandingReport(decodeResult, data2.split(","));
4048
+ break;
4049
+ case "PR":
4050
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
4051
+ break;
4052
+ case "PS":
4053
+ _H1Helper.processPS(decodeResult, data2.split(","));
4054
+ break;
4055
+ case "RF":
4056
+ case "RI":
4057
+ case "RM":
4058
+ case "RP":
4059
+ case "RS":
4060
+ FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
4061
+ break;
4062
+ case "RN":
4063
+ ResultFormatter.routeNumber(decodeResult, data2);
4064
+ break;
4065
+ case "RW":
4066
+ processRunway(decodeResult, data2.split(":"));
4067
+ break;
4068
+ case "SN":
4069
+ decodeResult.raw.serial_number = data2;
4070
+ break;
4071
+ case "SP":
4072
+ ResultFormatter.startPoint(decodeResult, data2);
4073
+ break;
4074
+ case "TD":
4075
+ processTimeOfDeparture(decodeResult, data2.split(","));
4076
+ break;
4077
+ case "TS":
4078
+ _H1Helper.processTimeStamp(decodeResult, data2.split(","));
4079
+ break;
4080
+ case "VR":
4081
+ ResultFormatter.version(decodeResult, parseInt(data2, 10) / 10);
4082
+ break;
4083
+ case "WD":
4084
+ processWindData(decodeResult, data2);
4085
+ break;
4086
+ case "WQ":
4087
+ processWeatherQuery(decodeResult, data2.split(":"));
4088
+ break;
4089
+ default:
4090
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
4091
+ }
4092
+ }
4093
+ ResultFormatter.checksumAlgorithm(decodeResult, checksumAlgorithmUsed);
4094
+ ResultFormatter.checksum(decodeResult, checksum);
4095
+ return true;
4275
4096
  }
4276
- parseHeader(header, results) {
4277
- const fields = header.split("/");
4278
- if (fields.length < 3) {
4279
- ResultFormatter.unknown(results, header, "/");
4280
- return;
4097
+ static processPS(decodeResult, data) {
4098
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
4099
+ data[0]
4100
+ );
4101
+ if (position) {
4102
+ ResultFormatter.position(decodeResult, position);
4281
4103
  }
4282
- const msgInfo = fields[0].split(/\s+/);
4283
- if (msgInfo.length === 3) {
4284
- ResultFormatter.unknownArr(results, msgInfo.slice(0, 2), " ");
4285
- ResultFormatter.flightNumber(results, msgInfo[2]);
4286
- } else {
4287
- ResultFormatter.unknown(results, header, "/");
4288
- return;
4104
+ if (data.length === 9) {
4105
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
4106
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
4107
+ ResultFormatter.temperature(decodeResult, data[6]);
4108
+ ResultFormatter.unknown(decodeResult, data[7]);
4109
+ ResultFormatter.unknown(decodeResult, data[8]);
4289
4110
  }
4290
- const otherInfo1 = fields[1].split(/\s+/);
4291
- if (otherInfo1.length === 2) {
4292
- ResultFormatter.day(results, parseInt(otherInfo1[0], 10));
4293
- ResultFormatter.departureAirport(results, otherInfo1[1]);
4294
- } else {
4295
- ResultFormatter.unknownArr(results, otherInfo1, " ");
4111
+ if (data.length === 14) {
4112
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
4113
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
4114
+ ResultFormatter.temperature(decodeResult, data[7]);
4115
+ ResultFormatter.unknownArr(decodeResult, data.slice(8));
4296
4116
  }
4297
- const otherInfo2 = fields[2].split(/\s+/);
4298
- if (otherInfo2.length === 2) {
4299
- ResultFormatter.arrivalAirport(results, otherInfo2[0]);
4300
- ResultFormatter.tail(results, otherInfo2[1].replace(".", ""));
4301
- } else {
4302
- ResultFormatter.unknownArr(results, otherInfo2, " ");
4117
+ }
4118
+ static processPosition(decodeResult, data) {
4119
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
4120
+ data[0]
4121
+ );
4122
+ if (position) {
4123
+ ResultFormatter.position(decodeResult, position);
4303
4124
  }
4304
- if (fields.length > 3) {
4305
- ResultFormatter.unknownArr(results, fields.slice(3), "/");
4125
+ if (data.length >= 10) {
4126
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
4127
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
4128
+ ResultFormatter.temperature(decodeResult, data[7]);
4129
+ ResultFormatter.unknown(decodeResult, data[8]);
4130
+ ResultFormatter.unknown(decodeResult, data[9]);
4131
+ }
4132
+ if (data.length >= 14) {
4133
+ ResultFormatter.unknownArr(decodeResult, data.slice(10));
4306
4134
  }
4307
4135
  }
4308
- parseTags(part, results) {
4309
- const kvPair = part.split(/\s+/);
4310
- if (kvPair.length < 2) {
4311
- ResultFormatter.unknown(results, part, "/");
4312
- return;
4136
+ static processTimeStamp(decodeResult, data) {
4137
+ if (data.length > 2) {
4138
+ const positionData = data.slice(1);
4139
+ positionData[0] = positionData[0].substring(6);
4140
+ this.processPosition(decodeResult, positionData);
4313
4141
  }
4314
- const tag = kvPair[0];
4315
- const val = kvPair.slice(1).join(" ");
4316
- switch (tag) {
4317
- case "POS":
4318
- const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
4319
- const posResult = val.match(posRegex);
4320
- const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.latd === "S" ? -1 : 1);
4321
- const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
4322
- const position = {
4323
- latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
4324
- longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
4325
- };
4326
- ResultFormatter.position(results, position);
4327
- break;
4328
- case "ALT":
4329
- ResultFormatter.altitude(results, parseInt(val.replace("+", ""), 10));
4330
- break;
4331
- case "FL":
4332
- ResultFormatter.altitude(results, parseInt(val, 10) * 100);
4333
- break;
4334
- case "MCH":
4335
- ResultFormatter.mach(results, parseInt(val, 10) / 1e3);
4336
- break;
4337
- case "SPD":
4338
- ResultFormatter.groundspeed(results, parseInt(val, 10));
4339
- break;
4340
- case "TAS":
4341
- ResultFormatter.airspeed(results, parseInt(val, 10));
4342
- break;
4343
- case "SAT":
4344
- ResultFormatter.temperature(results, val);
4345
- break;
4346
- case "FB":
4347
- break;
4348
- case "FOB":
4349
- ResultFormatter.currentFuel(
4350
- results,
4351
- parseInt(val.replace(/\D/g, ""), 10)
4352
- );
4353
- break;
4354
- case "UTC":
4355
- ResultFormatter.time_of_day(
4356
- results,
4357
- DateTimeUtils.convertHHMMSSToTod(val)
4358
- );
4359
- break;
4360
- case "ETA":
4361
- const hhmm = val.split(".")[0].replace(":", "");
4362
- ResultFormatter.eta(results, DateTimeUtils.convertHHMMSSToTod(hhmm));
4363
- break;
4364
- case "HDG":
4365
- ResultFormatter.heading(results, parseInt(val, 10));
4366
- break;
4367
- case "NWYP":
4368
- results.raw.next_waypoint = val;
4369
- break;
4370
- case "SWN":
4371
- ResultFormatter.unknown(results, part, "/");
4372
- break;
4373
- case "DWN":
4374
- ResultFormatter.unknown(results, part, "/");
4375
- break;
4376
- case "AD":
4377
- break;
4378
- default:
4379
- ResultFormatter.unknown(results, part, "/");
4142
+ let time = DateTimeUtils.convertDateTimeToEpoch(
4143
+ data[0],
4144
+ data[1].substring(0, 6)
4145
+ );
4146
+ if (Number.isNaN(time)) {
4147
+ const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
4148
+ time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
4380
4149
  }
4150
+ decodeResult.raw.message_timestamp = time;
4381
4151
  }
4382
- parseCsvFormat(text, results) {
4383
- const csvParts = text.split(",");
4384
- const header = csvParts[0].trim().split(/\s+/);
4385
- ResultFormatter.unknown(results, header[0], " ");
4386
- ResultFormatter.unknown(results, header[1], " ");
4387
- ResultFormatter.position(
4388
- results,
4389
- CoordinateUtils.decodeStringCoordinates(header[2])
4390
- );
4391
- ResultFormatter.unknown(results, csvParts[1]);
4392
- ResultFormatter.time_of_day(
4393
- results,
4394
- DateTimeUtils.convertHHMMSSToTod(csvParts[2])
4152
+ };
4153
+ function processETA(data, decodeResult, fields, i) {
4154
+ if (data.length === 5) {
4155
+ ResultFormatter.day(decodeResult, Number(data.substring(0, 1)));
4156
+ ResultFormatter.eta(
4157
+ decodeResult,
4158
+ DateTimeUtils.convertHHMMSSToTod(data.substring(1))
4395
4159
  );
4396
- ResultFormatter.unknownArr(results, csvParts.slice(4, 6), ",");
4397
- ResultFormatter.temperature(
4398
- results,
4399
- ((csvParts[6].charAt(0) === "M" ? -1 : 1) * parseInt(csvParts[6].slice(1), 10)).toString()
4160
+ } else if (data.length === 6) {
4161
+ ResultFormatter.day(decodeResult, Number(data.substring(0, 2)));
4162
+ ResultFormatter.eta(
4163
+ decodeResult,
4164
+ DateTimeUtils.convertHHMMSSToTod(data.substring(2))
4400
4165
  );
4401
- ResultFormatter.airspeed(results, parseInt(csvParts[7], 10));
4402
- ResultFormatter.currentFuel(results, parseInt(csvParts[8], 10));
4166
+ } else {
4167
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
4403
4168
  }
4404
- };
4405
-
4406
- // lib/plugins/Label_83.ts
4407
- var Label_83 = class extends DecoderPlugin {
4408
- name = "label-83";
4409
- qualifiers() {
4410
- return {
4411
- labels: ["83"]
4412
- };
4169
+ }
4170
+ function processAirField(decodeResult, data) {
4171
+ if (data.length === 2) {
4172
+ ResultFormatter.departureAirport(decodeResult, data[0]);
4173
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
4174
+ } else {
4175
+ ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
4413
4176
  }
4414
- decode(message, options = {}) {
4415
- const decodeResult = this.defaultResult();
4416
- decodeResult.decoder.name = this.name;
4417
- decodeResult.message = message;
4418
- decodeResult.formatted.description = "Airline Defined";
4419
- decodeResult.decoded = true;
4420
- const text = message.text;
4421
- if (text.substring(0, 10) === "4DH3 ETAT2") {
4422
- const fields = text.split(/\s+/);
4423
- if (fields[2].length > 5) {
4424
- decodeResult.raw.day = fields[2].substring(5);
4425
- }
4426
- ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
4427
- const subfields = fields[3].split("/");
4428
- ResultFormatter.departureAirport(decodeResult, subfields[0]);
4429
- ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
4430
- ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
4431
- ResultFormatter.eta(
4432
- decodeResult,
4433
- DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")
4434
- );
4435
- } else if (text.substring(0, 5) === "001PR") {
4436
- decodeResult.raw.day = text.substring(5, 7);
4437
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
4438
- text.substring(13, 28).replace(/\./g, "")
4439
- );
4440
- if (position) {
4441
- ResultFormatter.position(decodeResult, position);
4442
- }
4443
- ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
4444
- ResultFormatter.unknown(decodeResult, text.substring(33));
4445
- } else {
4446
- const fields = text.replace(/\s/g, "").split(",");
4447
- if (fields.length === 9) {
4448
- ResultFormatter.departureAirport(decodeResult, fields[0]);
4449
- ResultFormatter.arrivalAirport(decodeResult, fields[1]);
4450
- decodeResult.raw.day = fields[2].substring(0, 2);
4451
- decodeResult.raw.time = fields[2].substring(2);
4452
- ResultFormatter.position(decodeResult, {
4453
- latitude: Number(fields[3].replace(/\s/g, "")),
4454
- longitude: Number(fields[4].replace(/\s/g, ""))
4455
- });
4456
- ResultFormatter.altitude(decodeResult, Number(fields[5]));
4457
- ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
4458
- ResultFormatter.heading(decodeResult, Number(fields[7]));
4459
- ResultFormatter.unknown(decodeResult, fields[8]);
4460
- } else {
4461
- decodeResult.decoded = false;
4462
- ResultFormatter.unknown(decodeResult, text);
4463
- }
4177
+ }
4178
+ function processTimeOfDeparture(decodeResult, data) {
4179
+ if (data.length === 2) {
4180
+ decodeResult.raw.plannedDepartureTime = data[0];
4181
+ decodeResult.formatted.items.push({
4182
+ type: "ptd",
4183
+ code: "ptd",
4184
+ label: "Planned Departure Time",
4185
+ value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
4186
+ });
4187
+ decodeResult.raw.plannedDepartureTime = data[1];
4188
+ decodeResult.formatted.items.push({
4189
+ type: "etd",
4190
+ code: "etd",
4191
+ label: "Estimated Departure Time",
4192
+ value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
4193
+ });
4194
+ } else {
4195
+ ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
4196
+ }
4197
+ }
4198
+ function processIdentification(decodeResult, data) {
4199
+ ResultFormatter.tail(decodeResult, data[0]);
4200
+ if (data.length > 1) {
4201
+ ResultFormatter.flightNumber(decodeResult, data[1]);
4202
+ }
4203
+ if (data.length > 2) {
4204
+ decodeResult.raw.mission_number = data[2];
4205
+ }
4206
+ }
4207
+ function processDT(decodeResult, data) {
4208
+ if (data.length === 9) {
4209
+ ResultFormatter.unknown(decodeResult, data[0]);
4210
+ if (!decodeResult.raw.arrival_icao) {
4211
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
4464
4212
  }
4465
- if (decodeResult.decoded) {
4466
- if (!decodeResult.remaining.text)
4467
- decodeResult.decoder.decodeLevel = "full";
4468
- else decodeResult.decoder.decodeLevel = "partial";
4469
- } else {
4470
- decodeResult.decoder.decodeLevel = "none";
4213
+ ResultFormatter.arrivalRunway(decodeResult, data[2]);
4214
+ ResultFormatter.currentFuel(decodeResult, parseInt(data[3], 10));
4215
+ ResultFormatter.eta(
4216
+ decodeResult,
4217
+ DateTimeUtils.convertHHMMSSToTod(data[4])
4218
+ );
4219
+ ResultFormatter.unknown(decodeResult, data[5]);
4220
+ ResultFormatter.position(
4221
+ decodeResult,
4222
+ CoordinateUtils.decodeStringCoordinates(data[6])
4223
+ );
4224
+ ResultFormatter.unknown(decodeResult, data[7]);
4225
+ ResultFormatter.unknown(decodeResult, data[8]);
4226
+ return;
4227
+ }
4228
+ if (data.length === 4 || data.length === 5) {
4229
+ if (!decodeResult.raw.arrival_icao) {
4230
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
4471
4231
  }
4472
- return decodeResult;
4232
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
4233
+ ResultFormatter.currentFuel(decodeResult, parseInt(data[2], 10));
4234
+ ResultFormatter.eta(
4235
+ decodeResult,
4236
+ DateTimeUtils.convertHHMMSSToTod(data[3])
4237
+ );
4238
+ if (data.length > 4) {
4239
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
4240
+ }
4241
+ return;
4473
4242
  }
4474
- };
4475
-
4476
- // lib/plugins/Label_8E.ts
4477
- var Label_8E = class extends DecoderPlugin {
4478
- name = "label-8e";
4479
- qualifiers() {
4480
- return {
4481
- labels: ["8E"]
4482
- };
4243
+ ResultFormatter.unknownArr(decodeResult, data, ",");
4244
+ }
4245
+ function processLandingReport(decodeResult, data) {
4246
+ if (data.length === 19) {
4247
+ ResultFormatter.unknown(decodeResult, data[1]);
4248
+ ResultFormatter.flightNumber(decodeResult, data[2]);
4249
+ ResultFormatter.departureAirport(decodeResult, data[3]);
4250
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
4251
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
4252
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
4253
+ } else {
4254
+ ResultFormatter.unknown(decodeResult, data.join(","));
4255
+ }
4256
+ }
4257
+ function processCenterOfGravity(decodeResult, data) {
4258
+ if (data.length === 1) {
4259
+ if (data[0] !== void 0 && data[0] !== "") {
4260
+ ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10);
4261
+ }
4262
+ } else if (data.length === 3) {
4263
+ if (data[0] !== void 0 && data[0] !== "") {
4264
+ ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10, "center");
4265
+ }
4266
+ if (data[1] !== void 0 && data[1] !== "") {
4267
+ ResultFormatter.cg(decodeResult, parseInt(data[1], 10) / 10, "lower");
4268
+ }
4269
+ if (data[2] !== void 0 && data[2] !== "") {
4270
+ ResultFormatter.cg(decodeResult, parseInt(data[2], 10) / 10, "upper");
4271
+ }
4272
+ } else {
4273
+ ResultFormatter.unknown(decodeResult, data.join(","));
4483
4274
  }
4484
- decode(message, options = {}) {
4485
- const decodeResult = this.defaultResult();
4486
- decodeResult.decoder.name = this.name;
4487
- decodeResult.formatted.description = "ETA Report";
4488
- decodeResult.message = message;
4489
- const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
4490
- const results = message.text.match(regex);
4491
- if (results?.groups) {
4492
- if (options.debug) {
4493
- console.log("Label 8E ETA: groups");
4494
- console.log(results.groups);
4495
- }
4496
- ResultFormatter.eta(
4275
+ }
4276
+ function parseMessageType(decodeResult, messagePart) {
4277
+ const messageParts = messagePart.split(",");
4278
+ const messageType = messageParts[0];
4279
+ if (messageType.startsWith("POS")) {
4280
+ H1Helper.processPosition(decodeResult, messagePart.substring(3).split(","));
4281
+ return processMessageType(decodeResult, "POS");
4282
+ } else if (messageType.length === 6) {
4283
+ const part1 = processMessageType(decodeResult, messageType.substring(0, 3));
4284
+ const description = decodeResult.formatted.description;
4285
+ const part2 = processMessageType(decodeResult, messageType.substring(3, 6));
4286
+ decodeResult.formatted.description = description + " for " + decodeResult.formatted.description;
4287
+ if (messageParts.length > 1) {
4288
+ ResultFormatter.unknown(
4497
4289
  decodeResult,
4498
- DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta)
4290
+ messageParts.slice(1).join(","),
4291
+ "/"
4499
4292
  );
4500
- ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
4501
4293
  }
4502
- decodeResult.decoded = true;
4503
- decodeResult.decoder.decodeLevel = "full";
4504
- return decodeResult;
4294
+ return part1 && part2;
4505
4295
  }
4506
- };
4507
-
4508
- // lib/plugins/Label_B6.ts
4509
- var Label_B6_Forwardslash = class extends DecoderPlugin {
4510
- name = "label-b6-forwardslash";
4511
- qualifiers() {
4512
- return {
4513
- labels: ["B6"],
4514
- preambles: ["/"]
4515
- };
4296
+ if (messageParts.length > 1) {
4297
+ ResultFormatter.unknown(decodeResult, messageParts.slice(1).join(","), "/");
4516
4298
  }
4517
- decode(message, options = {}) {
4518
- const decodeResult = this.defaultResult();
4519
- decodeResult.decoder.name = this.name;
4520
- decodeResult.formatted.description = "CPDLC Message";
4521
- decodeResult.message = message;
4522
- if (options.debug) {
4523
- console.log("CPDLC: " + message);
4524
- }
4525
- return decodeResult;
4299
+ return processMessageType(decodeResult, messageType);
4300
+ }
4301
+ function processMessageType(decodeResult, type) {
4302
+ if (type === "FPN") {
4303
+ decodeResult.formatted.description = "Flight Plan";
4304
+ } else if (type === "FTX") {
4305
+ decodeResult.formatted.description = "Free Text";
4306
+ } else if (type === "INI") {
4307
+ decodeResult.formatted.description = "Initial Report";
4308
+ } else if (type === "INR") {
4309
+ decodeResult.formatted.description = "In-Range Report";
4310
+ } else if (type === "LDI") {
4311
+ decodeResult.formatted.description = "Load Distribution Information";
4312
+ } else if (type === "PER") {
4313
+ decodeResult.formatted.description = "Performance Report";
4314
+ } else if (type === "POS") {
4315
+ decodeResult.formatted.description = "Position Report";
4316
+ } else if (type === "PRG") {
4317
+ decodeResult.formatted.description = "Progress Report";
4318
+ } else if (type === "PWI") {
4319
+ decodeResult.formatted.description = "Pilot Weather Information";
4320
+ } else if (type === "WXR") {
4321
+ decodeResult.formatted.description = "Weather Report";
4322
+ } else if (type === "REJ") {
4323
+ decodeResult.formatted.description = "Reject";
4324
+ } else if (type === "REQ") {
4325
+ decodeResult.formatted.description = "Request";
4326
+ } else if (type === "RES") {
4327
+ decodeResult.formatted.description = "Response";
4328
+ } else {
4329
+ decodeResult.formatted.description = "Unknown H1 Message";
4330
+ return false;
4526
4331
  }
4527
- };
4528
-
4529
- // lib/plugins/Label_ColonComma.ts
4530
- var Label_ColonComma = class extends DecoderPlugin {
4531
- name = "label-colon-comma";
4532
- qualifiers() {
4533
- return {
4534
- labels: [":;"]
4535
- };
4332
+ return true;
4333
+ }
4334
+ function processDateCode(decodeResult, data) {
4335
+ if (data.length === 1) {
4336
+ } else if (data.length === 2) {
4337
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
4338
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
4339
+ decodeResult.raw.message_timestamp = time;
4536
4340
  }
4537
- decode(message, options = {}) {
4538
- const decodeResult = this.defaultResult();
4539
- decodeResult.decoder.name = this.name;
4540
- decodeResult.raw.frequency = Number(message.text) / 1e3;
4541
- decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
4542
- decodeResult.formatted.items.push({
4543
- type: "frequency",
4544
- label: "Frequency",
4545
- value: `${decodeResult.raw.frequency} MHz`,
4546
- code: "FREQ"
4547
- });
4548
- decodeResult.decoded = true;
4549
- decodeResult.decoder.decodeLevel = "full";
4550
- return decodeResult;
4341
+ }
4342
+ function processWeatherQuery(decodeResult, data) {
4343
+ if (data.length !== 2) {
4344
+ ResultFormatter.unknown(decodeResult, data.join(":"), "WQ/");
4345
+ return;
4551
4346
  }
4552
- };
4347
+ const alts = data[0].split(".");
4348
+ const route = data[1].split(".");
4349
+ ResultFormatter.requestedAltitudes(
4350
+ decodeResult,
4351
+ alts.map((a) => parseInt(a, 10) * 100)
4352
+ );
4353
+ const waypoints = route.map((wp) => {
4354
+ return { name: wp };
4355
+ });
4356
+ ResultFormatter.route(decodeResult, { waypoints });
4357
+ }
4358
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
4359
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
4360
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
4361
+ const timeFormat = date ? "epoch" : "tod";
4362
+ const lastWaypoint = RouteUtils.getWaypoint(last);
4363
+ lastWaypoint.time = lastTime;
4364
+ lastWaypoint.timeFormat = timeFormat;
4365
+ const nextWaypoint = RouteUtils.getWaypoint(next);
4366
+ nextWaypoint.time = nextTime;
4367
+ nextWaypoint.timeFormat = timeFormat;
4368
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
4369
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
4370
+ ResultFormatter.route(decodeResult, { waypoints });
4371
+ }
4372
+ function processWindData(decodeResult, message) {
4373
+ const wind = [];
4374
+ const flightLevel = Number(message.slice(0, 3));
4375
+ const fields = message.slice(4).split(".");
4376
+ fields.forEach((field) => {
4377
+ if (field.length < 4) {
4378
+ return;
4379
+ }
4380
+ const data = field.split(",");
4381
+ const waypoint = { name: data[0] };
4382
+ const windData = data[1];
4383
+ const windDirection = parseInt(windData.slice(0, 3), 10);
4384
+ const windSpeed = parseInt(windData.slice(3), 10);
4385
+ if (data.length === 3) {
4386
+ const tempData = data[2];
4387
+ const tempFlightLevel = Number(tempData.slice(0, 3));
4388
+ const tempString = tempData.slice(3);
4389
+ const tempDegrees = Number(tempString.substring(1)) * (tempString.charAt(0) === "M" ? -1 : 1);
4390
+ wind.push({
4391
+ waypoint,
4392
+ flightLevel,
4393
+ windDirection,
4394
+ windSpeed,
4395
+ temperature: {
4396
+ flightLevel: tempFlightLevel,
4397
+ degreesC: tempDegrees
4398
+ }
4399
+ });
4400
+ } else {
4401
+ wind.push({
4402
+ waypoint,
4403
+ flightLevel,
4404
+ windDirection,
4405
+ windSpeed
4406
+ });
4407
+ }
4408
+ });
4409
+ ResultFormatter.windData(decodeResult, wind);
4410
+ }
4411
+ function processRunway(decodeResult, data) {
4412
+ const parts = data[0].split(".");
4413
+ const more = parts[0].split(",");
4414
+ ResultFormatter.departureRunway(decodeResult, more[0]);
4415
+ ResultFormatter.unknownArr(decodeResult, more.slice(1), ",");
4416
+ ResultFormatter.unknownArr(decodeResult, parts.slice(1), ".");
4417
+ ResultFormatter.departureAirport(decodeResult, data[1].split(",")[0]);
4418
+ ResultFormatter.unknownArr(decodeResult, data[1].split(",").slice(1), ",");
4419
+ }
4420
+ function crc16IbmSdlcRev(data) {
4421
+ let crc = 65535;
4422
+ const bytes = Buffer.from(data, "ascii");
4423
+ for (const byte of bytes) {
4424
+ crc ^= byte;
4425
+ for (let i = 0; i < 8; i++) {
4426
+ if ((crc & 1) !== 0) {
4427
+ crc = crc >>> 1 ^ 33800;
4428
+ } else {
4429
+ crc = crc >>> 1;
4430
+ }
4431
+ }
4432
+ }
4433
+ crc = (crc ^ 65535) & 65535;
4434
+ const nibble1 = crc >> 12 & 15;
4435
+ const nibble2 = crc >> 8 & 15;
4436
+ const nibble3 = crc >> 4 & 15;
4437
+ const nibble4 = crc & 15;
4438
+ return nibble4 << 12 | nibble3 << 8 | nibble2 << 4 | nibble1;
4439
+ }
4440
+ function crc16Genibus(data) {
4441
+ let crc = 65535;
4442
+ const polynomial = 4129;
4443
+ const bytes = Buffer.from(data, "ascii");
4444
+ for (const byte of bytes) {
4445
+ crc ^= byte << 8;
4446
+ for (let i = 0; i < 8; i++) {
4447
+ if ((crc & 32768) !== 0) {
4448
+ crc = (crc << 1 ^ polynomial) & 65535;
4449
+ } else {
4450
+ crc = crc << 1 & 65535;
4451
+ }
4452
+ }
4453
+ }
4454
+ return (crc ^ 65535) & 65535;
4455
+ }
4553
4456
 
4554
4457
  // lib/plugins/Label_H1.ts
4555
4458
  var Label_H1 = class extends DecoderPlugin {
4556
4459
  name = "label-h1";
4557
4460
  qualifiers() {
4558
4461
  return {
4559
- labels: ["H1"]
4462
+ labels: ["1J", "2J", "2P", "4J", "80", "H1"]
4560
4463
  };
4561
4464
  }
4562
4465
  decode(message, options = {}) {
@@ -4564,33 +4467,58 @@ var Label_H1 = class extends DecoderPlugin {
4564
4467
  decodeResult.decoder.name = this.name;
4565
4468
  decodeResult.message = message;
4566
4469
  const msg = message.text.replace(/\n|\r/g, "");
4567
- const parts = msg.split("#");
4568
4470
  let decoded = false;
4471
+ decoded = H1Helper.decodeH1Message(decodeResult, msg);
4472
+ if (decoded) {
4473
+ return this.processDecodeResult(decodeResult, decoded, options, message);
4474
+ }
4569
4475
  if (msg.startsWith("/")) {
4570
4476
  const headerData = msg.split(".");
4571
- const decoded2 = H1Helper.decodeH1Message(
4477
+ decoded = H1Helper.decodeH1Message(
4572
4478
  decodeResult,
4573
4479
  headerData.slice(1).join(".")
4574
4480
  );
4575
- if (decoded2) {
4481
+ if (decoded) {
4576
4482
  decodeResult.remaining.text = headerData[0] + "." + decodeResult.remaining.text;
4577
- decodeResult.decoded = decoded2;
4578
- decodeResult.decoder.decodeLevel = "partial";
4483
+ return this.processDecodeResult(
4484
+ decodeResult,
4485
+ decoded,
4486
+ options,
4487
+ message
4488
+ );
4579
4489
  }
4580
- return decodeResult;
4581
- } else if (parts.length === 1) {
4582
- decoded = H1Helper.decodeH1Message(decodeResult, msg);
4583
- } else if (parts.length == 2) {
4584
- const offset = parts[0] === "- " || isNaN(parseInt(parts[1][1])) ? 3 : 4;
4490
+ }
4491
+ const hashParts = msg.split("#");
4492
+ if (hashParts.length == 2) {
4493
+ const offset = hashParts[0] === "- " || isNaN(parseInt(hashParts[1][1])) ? 3 : 4;
4585
4494
  decoded = H1Helper.decodeH1Message(
4586
4495
  decodeResult,
4587
- msg.slice(parts[0].length + offset)
4496
+ msg.slice(hashParts[0].length + offset)
4588
4497
  );
4589
- if (decoded && parts[0].length > 0) {
4590
- ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
4591
- decodeResult.remaining.text = parts[0].substring(0, 4) + "#" + parts[1].substring(0, offset - 1) + "/" + decodeResult.remaining.text;
4498
+ if (decoded && hashParts[0].length > 0) {
4499
+ ResultFormatter.flightNumber(decodeResult, hashParts[0].substring(4));
4500
+ decodeResult.remaining.text = hashParts[0].substring(0, 4) + "#" + hashParts[1].substring(0, offset - 1) + "/" + decodeResult.remaining.text;
4592
4501
  }
4502
+ if (decoded) {
4503
+ return this.processDecodeResult(
4504
+ decodeResult,
4505
+ decoded,
4506
+ options,
4507
+ message
4508
+ );
4509
+ }
4510
+ }
4511
+ const slashParts = msg.split("/");
4512
+ if (slashParts[0].length > 3) {
4513
+ decoded = H1Helper.decodeH1Message(
4514
+ decodeResult,
4515
+ msg.slice(slashParts[0].length - 3)
4516
+ );
4517
+ decodeResult.remaining.text = slashParts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
4593
4518
  }
4519
+ return this.processDecodeResult(decodeResult, decoded, options, message);
4520
+ }
4521
+ processDecodeResult(decodeResult, decoded, options, message) {
4594
4522
  decodeResult.decoded = decoded;
4595
4523
  decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
4596
4524
  if (decodeResult.formatted.items.length === 0) {
@@ -6223,7 +6151,6 @@ var MessageDecoder = class {
6223
6151
  this.registerPlugin(new Label_16_N_Space(this));
6224
6152
  this.registerPlugin(new Label_16_POSA1(this));
6225
6153
  this.registerPlugin(new Label_16_TOD(this));
6226
- this.registerPlugin(new Label_1J_2J_FTX(this));
6227
6154
  this.registerPlugin(new Label_1L_3Line(this));
6228
6155
  this.registerPlugin(new Label_1L_070(this));
6229
6156
  this.registerPlugin(new Label_1L_660(this));
@@ -6236,7 +6163,6 @@ var MessageDecoder = class {
6236
6163
  this.registerPlugin(new Label_2P_FM3(this));
6237
6164
  this.registerPlugin(new Label_2P_FM4(this));
6238
6165
  this.registerPlugin(new Label_2P_FM5(this));
6239
- this.registerPlugin(new Label_2P_POS(this));
6240
6166
  this.registerPlugin(new Label_30_Slash_EA(this));
6241
6167
  this.registerPlugin(new Label_44_ETA(this));
6242
6168
  this.registerPlugin(new Label_44_IN(this));
@@ -6249,7 +6175,6 @@ var MessageDecoder = class {
6249
6175
  this.registerPlugin(new Label_4A_DIS(this));
6250
6176
  this.registerPlugin(new Label_4A_DOOR(this));
6251
6177
  this.registerPlugin(new Label_4A_Slash_01(this));
6252
- this.registerPlugin(new Label_4J_POS(this));
6253
6178
  this.registerPlugin(new Label_4N(this));
6254
6179
  this.registerPlugin(new Label_4T_AGFSR(this));
6255
6180
  this.registerPlugin(new Label_4T_ETA(this));