@airframes/acars-decoder 1.8.7 → 1.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -590,8 +590,11 @@ var ResultFormatter = class {
590
590
  value: decodeResult.raw.fuel_remaining.toString()
591
591
  });
592
592
  }
593
+ static checksumAlgorithm(decodeResult, value) {
594
+ decodeResult.raw.checksum_algorithm = value;
595
+ }
593
596
  static checksum(decodeResult, value) {
594
- decodeResult.raw.checksum = Number("0x" + value);
597
+ decodeResult.raw.checksum = value;
595
598
  decodeResult.formatted.items.push({
596
599
  type: "message_checksum",
597
600
  code: "CHECKSUM",
@@ -1975,9 +1978,14 @@ function addCompanyRoute(decodeResult, value) {
1975
1978
  // lib/utils/h1_helper.ts
1976
1979
  var H1Helper = class _H1Helper {
1977
1980
  static decodeH1Message(decodeResult, message) {
1978
- const checksum = message.slice(-4);
1981
+ const checksum = parseInt(message.slice(-4), 16);
1979
1982
  const data = message.slice(0, message.length - 4);
1980
- if (calculateChecksum(data) !== checksum) {
1983
+ let checksumAlgorithmUsed = "";
1984
+ if (crc16IbmSdlcRev(data) === checksum) {
1985
+ checksumAlgorithmUsed = "IBM-SDLC reversed";
1986
+ } else if (crc16Genibus(data) === checksum) {
1987
+ checksumAlgorithmUsed = "GENIBUS";
1988
+ } else {
1981
1989
  decodeResult.decoded = false;
1982
1990
  decodeResult.decoder.decodeLevel = "none";
1983
1991
  return false;
@@ -2054,6 +2062,9 @@ var H1Helper = class _H1Helper {
2054
2062
  case "RN":
2055
2063
  ResultFormatter.routeNumber(decodeResult, data2);
2056
2064
  break;
2065
+ case "RW":
2066
+ processRunway(decodeResult, data2.split(":"));
2067
+ break;
2057
2068
  case "SN":
2058
2069
  decodeResult.raw.serial_number = data2;
2059
2070
  break;
@@ -2079,6 +2090,7 @@ var H1Helper = class _H1Helper {
2079
2090
  ResultFormatter.unknown(decodeResult, fields[i], "/");
2080
2091
  }
2081
2092
  }
2093
+ ResultFormatter.checksumAlgorithm(decodeResult, checksumAlgorithmUsed);
2082
2094
  ResultFormatter.checksum(decodeResult, checksum);
2083
2095
  return true;
2084
2096
  }
@@ -2193,29 +2205,42 @@ function processIdentification(decodeResult, data) {
2193
2205
  }
2194
2206
  }
2195
2207
  function processDT(decodeResult, data) {
2196
- if (!decodeResult.raw.arrival_icao) {
2197
- ResultFormatter.arrivalAirport(decodeResult, data[0]);
2198
- } else if (decodeResult.raw.arrival_icao != data[0]) {
2199
- ResultFormatter.unknownArr(decodeResult, data);
2208
+ if (data.length === 9) {
2209
+ ResultFormatter.unknown(decodeResult, data[0]);
2210
+ if (!decodeResult.raw.arrival_icao) {
2211
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
2212
+ }
2213
+ ResultFormatter.arrivalRunway(decodeResult, data[2]);
2214
+ ResultFormatter.currentFuel(decodeResult, parseInt(data[3], 10));
2215
+ ResultFormatter.eta(
2216
+ decodeResult,
2217
+ DateTimeUtils.convertHHMMSSToTod(data[4])
2218
+ );
2219
+ ResultFormatter.unknown(decodeResult, data[5]);
2220
+ ResultFormatter.position(
2221
+ decodeResult,
2222
+ CoordinateUtils.decodeStringCoordinates(data[6])
2223
+ );
2224
+ ResultFormatter.unknown(decodeResult, data[7]);
2225
+ ResultFormatter.unknown(decodeResult, data[8]);
2226
+ return;
2200
2227
  }
2201
- if (data.length > 1) {
2228
+ if (data.length === 4 || data.length === 5) {
2229
+ if (!decodeResult.raw.arrival_icao) {
2230
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
2231
+ }
2202
2232
  ResultFormatter.arrivalRunway(decodeResult, data[1]);
2203
- }
2204
- if (data.length > 2) {
2205
- ResultFormatter.currentFuel(decodeResult, Number(data[2]));
2206
- }
2207
- if (data.length > 3) {
2233
+ ResultFormatter.currentFuel(decodeResult, parseInt(data[2], 10));
2208
2234
  ResultFormatter.eta(
2209
2235
  decodeResult,
2210
2236
  DateTimeUtils.convertHHMMSSToTod(data[3])
2211
2237
  );
2238
+ if (data.length > 4) {
2239
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
2240
+ }
2241
+ return;
2212
2242
  }
2213
- if (data.length > 4) {
2214
- ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
2215
- }
2216
- if (data.length > 5) {
2217
- ResultFormatter.unknownArr(decodeResult, data);
2218
- }
2243
+ ResultFormatter.unknownArr(decodeResult, data, ",");
2219
2244
  }
2220
2245
  function processLandingReport(decodeResult, data) {
2221
2246
  if (data.length === 19) {
@@ -2279,7 +2304,9 @@ function processMessageType(decodeResult, type) {
2279
2304
  } else if (type === "FTX") {
2280
2305
  decodeResult.formatted.description = "Free Text";
2281
2306
  } else if (type === "INI") {
2282
- decodeResult.formatted.description = "Flight Plan Initial Report";
2307
+ decodeResult.formatted.description = "Initial Report";
2308
+ } else if (type === "LDI") {
2309
+ decodeResult.formatted.description = "Load Distribution Information";
2283
2310
  } else if (type === "PER") {
2284
2311
  decodeResult.formatted.description = "Performance Report";
2285
2312
  } else if (type === "POS") {
@@ -2344,11 +2371,14 @@ function processWindData(decodeResult, message) {
2344
2371
  const flightLevel = Number(message.slice(0, 3));
2345
2372
  const fields = message.slice(4).split(".");
2346
2373
  fields.forEach((field) => {
2374
+ if (field.length < 4) {
2375
+ return;
2376
+ }
2347
2377
  const data = field.split(",");
2348
2378
  const waypoint = { name: data[0] };
2349
2379
  const windData = data[1];
2350
- const windDirection = Number(windData.slice(0, 3));
2351
- const windSpeed = Number(windData.slice(3));
2380
+ const windDirection = parseInt(windData.slice(0, 3), 10);
2381
+ const windSpeed = parseInt(windData.slice(3), 10);
2352
2382
  if (data.length === 3) {
2353
2383
  const tempData = data[2];
2354
2384
  const tempFlightLevel = Number(tempData.slice(0, 3));
@@ -2375,7 +2405,16 @@ function processWindData(decodeResult, message) {
2375
2405
  });
2376
2406
  ResultFormatter.windData(decodeResult, wind);
2377
2407
  }
2378
- function calculateChecksum(data) {
2408
+ function processRunway(decodeResult, data) {
2409
+ const parts = data[0].split(".");
2410
+ const more = parts[0].split(",");
2411
+ ResultFormatter.departureRunway(decodeResult, more[0]);
2412
+ ResultFormatter.unknownArr(decodeResult, more.slice(1), ",");
2413
+ ResultFormatter.unknownArr(decodeResult, parts.slice(1), ".");
2414
+ ResultFormatter.departureAirport(decodeResult, data[1].split(",")[0]);
2415
+ ResultFormatter.unknownArr(decodeResult, data[1].split(",").slice(1), ",");
2416
+ }
2417
+ function crc16IbmSdlcRev(data) {
2379
2418
  let crc = 65535;
2380
2419
  const bytes = Buffer.from(data, "ascii");
2381
2420
  for (const byte of bytes) {
@@ -2393,7 +2432,23 @@ function calculateChecksum(data) {
2393
2432
  const nibble2 = crc >> 8 & 15;
2394
2433
  const nibble3 = crc >> 4 & 15;
2395
2434
  const nibble4 = crc & 15;
2396
- return `${nibble4.toString(16)}${nibble3.toString(16)}${nibble2.toString(16)}${nibble1.toString(16)}`.toUpperCase();
2435
+ return nibble4 << 12 | nibble3 << 8 | nibble2 << 4 | nibble1;
2436
+ }
2437
+ function crc16Genibus(data) {
2438
+ let crc = 65535;
2439
+ const polynomial = 4129;
2440
+ const bytes = Buffer.from(data, "ascii");
2441
+ for (const byte of bytes) {
2442
+ crc ^= byte << 8;
2443
+ for (let i = 0; i < 8; i++) {
2444
+ if ((crc & 32768) !== 0) {
2445
+ crc = (crc << 1 ^ polynomial) & 65535;
2446
+ } else {
2447
+ crc = crc << 1 & 65535;
2448
+ }
2449
+ }
2450
+ }
2451
+ return (crc ^ 65535) & 65535;
2397
2452
  }
2398
2453
 
2399
2454
  // lib/plugins/Label_1J_2J_FTX.ts
@@ -3992,7 +4047,7 @@ var Label_4N = class extends DecoderPlugin {
3992
4047
  if (fields[12].length > 1) {
3993
4048
  ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
3994
4049
  }
3995
- ResultFormatter.checksum(decodeResult, fields[32]);
4050
+ ResultFormatter.checksum(decodeResult, parseInt(fields[32], 16));
3996
4051
  ResultFormatter.unknownArr(
3997
4052
  decodeResult,
3998
4053
  [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter(
@@ -4501,7 +4556,7 @@ var Label_H1 = class extends DecoderPlugin {
4501
4556
  } else if (parts.length === 1) {
4502
4557
  decoded = H1Helper.decodeH1Message(decodeResult, msg);
4503
4558
  } else if (parts.length == 2) {
4504
- const offset = isNaN(parseInt(parts[1][1])) ? 3 : 4;
4559
+ const offset = parts[0] === "- " || isNaN(parseInt(parts[1][1])) ? 3 : 4;
4505
4560
  decoded = H1Helper.decodeH1Message(
4506
4561
  decodeResult,
4507
4562
  msg.slice(parts[0].length + offset)
@@ -4722,6 +4777,66 @@ var Label_H1_OHMA = class extends DecoderPlugin {
4722
4777
  }
4723
4778
  };
4724
4779
 
4780
+ // lib/plugins/Label_H1_Paren.ts
4781
+ var Label_H1_Paren = class extends DecoderPlugin {
4782
+ name = "label-h1-paren";
4783
+ qualifiers() {
4784
+ return {
4785
+ labels: ["H1"],
4786
+ preambles: ["("]
4787
+ };
4788
+ }
4789
+ decode(message) {
4790
+ let decodeResult = this.defaultResult();
4791
+ decodeResult.decoder.name = this.name;
4792
+ decodeResult.message = message;
4793
+ if (!message.text || !message.text.startsWith("(")) {
4794
+ decodeResult.decoded = false;
4795
+ return decodeResult;
4796
+ }
4797
+ const regex = /^\(POS-(?<flight>\w+)\s+(?<lat>-?\d{4,5}[NS])(?<lon>\d{5}[EW])\/(?<timestamp>\d{6})\s+F(?<alt>\d{3})\r?\nRMK\/FUEL\s+(?<fuel>\d{2,3}\.\d)\s+M(?<mach>\d\.\d{2})\)/;
4798
+ const match = message.text.match(regex);
4799
+ if (match && match.groups) {
4800
+ decodeResult.decoded = true;
4801
+ decodeResult.decoder.decodeLevel = "partial";
4802
+ decodeResult.formatted.description = "Position Report";
4803
+ ResultFormatter.flightNumber(decodeResult, match.groups.flight);
4804
+ ResultFormatter.position(decodeResult, {
4805
+ latitude: parseLat(match.groups.lat),
4806
+ longitude: parseLon(match.groups.lon)
4807
+ });
4808
+ ResultFormatter.time_of_day(
4809
+ decodeResult,
4810
+ DateTimeUtils.convertHHMMSSToTod(match.groups.timestamp)
4811
+ );
4812
+ ResultFormatter.altitude(
4813
+ decodeResult,
4814
+ parseInt(match.groups.alt, 10) * 100
4815
+ );
4816
+ ResultFormatter.currentFuel(decodeResult, parseFloat(match.groups.fuel));
4817
+ ResultFormatter.mach(decodeResult, parseFloat(match.groups.mach));
4818
+ ResultFormatter.unknown(decodeResult, "RMK");
4819
+ }
4820
+ return decodeResult;
4821
+ }
4822
+ };
4823
+ function parseLat(latStr) {
4824
+ const match = latStr.match(/(-?)(\d{2})(\d{2})([NS])/);
4825
+ if (!match) return NaN;
4826
+ let deg = parseInt(match[2]);
4827
+ let min = parseInt(match[3]);
4828
+ let sign = match[4] === "S" ? -1 : 1;
4829
+ return sign * (deg + min / 60);
4830
+ }
4831
+ function parseLon(lonStr) {
4832
+ const match = lonStr.match(/(\d{3})(\d{2})([EW])/);
4833
+ if (!match) return NaN;
4834
+ let deg = parseInt(match[1]);
4835
+ let min = parseInt(match[2]);
4836
+ let sign = match[3] === "W" ? -1 : 1;
4837
+ return sign * (deg + min / 60);
4838
+ }
4839
+
4725
4840
  // lib/plugins/Label_H1_StarPOS.ts
4726
4841
  var Label_H1_StarPOS = class extends DecoderPlugin {
4727
4842
  name = "label-h1-star-pos";
@@ -6117,6 +6232,7 @@ var MessageDecoder = class {
6117
6232
  this.registerPlugin(new Label_H2_02E(this));
6118
6233
  this.registerPlugin(new Label_H1_FLR(this));
6119
6234
  this.registerPlugin(new Label_H1_OHMA(this));
6235
+ this.registerPlugin(new Label_H1_Paren(this));
6120
6236
  this.registerPlugin(new Label_H1_WRN(this));
6121
6237
  this.registerPlugin(new Label_H1(this));
6122
6238
  this.registerPlugin(new Label_H1_StarPOS(this));