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