@airframes/acars-decoder 1.8.10 → 1.8.12

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