@airframes/acars-decoder 1.6.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1240,12 +1240,19 @@ var RouteUtils = class _RouteUtils {
1240
1240
  if (waypoint.latitude && waypoint.longitude) {
1241
1241
  s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
1242
1242
  }
1243
+ if (waypoint.offset) {
1244
+ s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
1245
+ }
1243
1246
  if (waypoint.time && waypoint.timeFormat) {
1244
1247
  s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
1245
1248
  }
1246
1249
  return s;
1247
1250
  }
1248
1251
  static getWaypoint(leg) {
1252
+ const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
1253
+ if (regex?.length == 4) {
1254
+ return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
1255
+ }
1249
1256
  const waypoint = leg.split(",");
1250
1257
  if (waypoint.length == 2) {
1251
1258
  const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
@@ -1253,10 +1260,11 @@ var RouteUtils = class _RouteUtils {
1253
1260
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1254
1261
  }
1255
1262
  }
1256
- if (leg.length == 14) {
1263
+ if (leg.length == 13 || leg.length == 14) {
1257
1264
  const position = CoordinateUtils.decodeStringCoordinates(leg);
1265
+ const name = waypoint.length == 2 ? waypoint[0] : "";
1258
1266
  if (position) {
1259
- return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1267
+ return { name, latitude: position.latitude, longitude: position.longitude };
1260
1268
  }
1261
1269
  }
1262
1270
  return { name: leg };
@@ -1317,7 +1325,7 @@ var FlightPlanUtils = class {
1317
1325
  addRoute(decodeResult, value);
1318
1326
  break;
1319
1327
  case "R":
1320
- addDepartureRunway(decodeResult, value);
1328
+ addRunway(decodeResult, value);
1321
1329
  break;
1322
1330
  default:
1323
1331
  if (allKnownFields) {
@@ -1331,41 +1339,106 @@ var FlightPlanUtils = class {
1331
1339
  return allKnownFields;
1332
1340
  }
1333
1341
  };
1342
+ function parseMessageType(decodeResult, messageType) {
1343
+ let decoded = true;
1344
+ const parts = messageType.split("#");
1345
+ if (parts.length == 1) {
1346
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1347
+ decoded = processPosition(decodeResult, parts[0].substring(3));
1348
+ }
1349
+ return decoded;
1350
+ } else if (parts.length == 2) {
1351
+ if (parts[0].length > 0) {
1352
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1353
+ decodeResult.raw.flight_number = parts[0].substring(3);
1354
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1355
+ }
1356
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1357
+ decoded = processPosition(decodeResult, parts[1].substring(6));
1358
+ }
1359
+ decodeResult.raw.message_type = messageType;
1360
+ return decoded;
1361
+ }
1362
+ decodeResult.remaining.text += messageType;
1363
+ return false;
1364
+ }
1334
1365
  function parseHeader(decodeResult, header) {
1335
1366
  let allKnownFields = true;
1336
1367
  const fields = header.split("/");
1337
- for (let i = 1; i < fields.length - 1; ++i) {
1368
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1369
+ for (let i = 1; i < fields.length; ++i) {
1338
1370
  if (fields[i].startsWith("FN")) {
1339
1371
  decodeResult.raw.flight_number = fields[i].substring(2);
1340
1372
  } else if (fields[i].startsWith("SN")) {
1341
1373
  decodeResult.raw.serial_number = fields[i].substring(2);
1342
1374
  } else if (fields[i].startsWith("TS")) {
1343
1375
  const ts = fields[i].substring(2).split(",");
1344
- decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1376
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1377
+ if (Number.isNaN(time)) {
1378
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1379
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1380
+ }
1381
+ decodeResult.raw.message_timestamp = time;
1382
+ } else if (fields[i].startsWith("PS")) {
1383
+ const pos = fields[i].substring(2);
1384
+ allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1385
+ } else if (fields[i].startsWith("DT")) {
1386
+ const icao = fields[i].substring(2);
1387
+ decodeResult.raw.arrival_icao = icao;
1388
+ decodeResult.formatted.items.push({
1389
+ type: "destination",
1390
+ code: "DST",
1391
+ label: "Destination",
1392
+ value: decodeResult.raw.arrival_icao
1393
+ });
1394
+ } else if (fields[i].startsWith("RF")) {
1395
+ decodeResult.formatted.items.push({
1396
+ type: "status",
1397
+ code: "ROUTE_STATUS",
1398
+ label: "Route Status",
1399
+ value: "Route Filed"
1400
+ });
1401
+ decodeResult.raw.route_status = "RF";
1402
+ if (fields[i].length > 2) {
1403
+ addRoute(decodeResult, fields[i].substring(2));
1404
+ }
1405
+ } else if (fields[i] == "RP") {
1406
+ decodeResult.raw.route_status = "RP";
1407
+ decodeResult.formatted.items.push({
1408
+ type: "status",
1409
+ code: "ROUTE_STATUS",
1410
+ label: "Route Status",
1411
+ value: "Route Planned"
1412
+ });
1413
+ decodeResult.raw.route_status = fields[i];
1414
+ } else if (fields[i] == "RI") {
1415
+ decodeResult.raw.route_status = "RI";
1416
+ decodeResult.formatted.items.push({
1417
+ type: "status",
1418
+ code: "ROUTE_STATUS",
1419
+ label: "Route Status",
1420
+ value: "Route Inactive"
1421
+ });
1345
1422
  } else {
1346
1423
  decodeResult.remaining.text += "/" + fields[i];
1347
1424
  allKnownFields = false;
1348
1425
  }
1349
1426
  }
1350
- decodeResult.raw.route_status = fields[fields.length - 1];
1351
- var text;
1352
- if (decodeResult.raw.route_status == "RP") {
1353
- text = "Route Planned";
1354
- } else if (decodeResult.raw.route_status == "RI") {
1355
- text = "Route Inactive";
1356
- } else if (decodeResult.raw.route_status == "RF") {
1357
- text = "Route Filed";
1358
- } else {
1359
- text = decodeResult.raw.route_status;
1360
- }
1361
- decodeResult.formatted.items.push({
1362
- type: "status",
1363
- code: "ROUTE_STATUS",
1364
- label: "Route Status",
1365
- value: text
1366
- });
1367
1427
  return allKnownFields;
1368
1428
  }
1429
+ function processPosition(decodeResult, value) {
1430
+ const position = CoordinateUtils.decodeStringCoordinates(value);
1431
+ if (position) {
1432
+ decodeResult.raw.position = position;
1433
+ decodeResult.formatted.items.push({
1434
+ type: "aircraft_position",
1435
+ code: "POS",
1436
+ label: "Aircraft Position",
1437
+ value: CoordinateUtils.coordinateString(position)
1438
+ });
1439
+ }
1440
+ return !!position;
1441
+ }
1369
1442
  function addArrivalAirport(decodeResult, value) {
1370
1443
  decodeResult.raw.arrival_icao = value;
1371
1444
  decodeResult.formatted.items.push({
@@ -1384,12 +1457,20 @@ function addDepartureAirport(decodeResult, value) {
1384
1457
  value: decodeResult.raw.departure_icao
1385
1458
  });
1386
1459
  }
1387
- function addDepartureRunway(decodeResult, value) {
1388
- decodeResult.raw.runway = value;
1460
+ function addRunway(decodeResult, value) {
1461
+ if (value.length === 8) {
1462
+ decodeResult.raw.arrival_runway = value.substring(4, 7);
1463
+ decodeResult.formatted.items.push({
1464
+ type: "runway",
1465
+ label: "Arrival Runway",
1466
+ value: decodeResult.raw.arrival_runway
1467
+ });
1468
+ }
1469
+ decodeResult.raw.departure_runway = value.substring(0, 3);
1389
1470
  decodeResult.formatted.items.push({
1390
1471
  type: "runway",
1391
- label: "Runway",
1392
- value: decodeResult.raw.runway
1472
+ label: "Departure Runway",
1473
+ value: decodeResult.raw.departure_runway
1393
1474
  });
1394
1475
  }
1395
1476
  function addRoute(decodeResult, value) {
@@ -1499,7 +1580,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1499
1580
  qualifiers() {
1500
1581
  return {
1501
1582
  labels: ["H1"],
1502
- preambles: ["POS", "#M1BPOS"]
1583
+ preambles: ["POS", "#M1BPOS", "/.POS"]
1503
1584
  //TODO - support data before #
1504
1585
  };
1505
1586
  }
@@ -1508,29 +1589,25 @@ var Label_H1_POS = class extends DecoderPlugin {
1508
1589
  decodeResult.decoder.name = this.name;
1509
1590
  decodeResult.formatted.description = "Position Report";
1510
1591
  decodeResult.message = message;
1592
+ decodeResult.remaining.text = "";
1511
1593
  const checksum = message.text.slice(-4);
1512
- const parts = message.text.replace("#M1B", "").replace("POS", "").slice(0, -4).split(",");
1513
- if (parts.length == 1 && parts[0].startsWith("/RF")) {
1514
- decodeResult.raw.route_status == "RF";
1515
- decodeResult.formatted.items.push({
1516
- type: "status",
1517
- code: "ROUTE_STATUS",
1518
- label: "Route Status",
1519
- value: "Route Filed"
1520
- });
1521
- decodeResult.raw.route = { waypoints: parts[0].substring(3, parts[0].length).split(".").map((leg) => RouteUtils.getWaypoint(leg)) };
1522
- decodeResult.formatted.items.push({
1523
- type: "aircraft_route",
1524
- code: "ROUTE",
1525
- label: "Aircraft Route",
1526
- value: RouteUtils.routeToString(decodeResult.raw.route)
1527
- });
1528
- processChecksum(decodeResult, checksum);
1529
- decodeResult.decoded = true;
1530
- decodeResult.decoder.decodeLevel = "full";
1594
+ const header = findHeader(message.text.slice(0, -4));
1595
+ const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1596
+ const parts = message.text.replace(header, "").slice(0, -4).split(",");
1597
+ if (parts.length == 1) {
1598
+ if (decoded) {
1599
+ processChecksum(decodeResult, checksum);
1600
+ decodeResult.decoded = true;
1601
+ decodeResult.decoder.decodeLevel = "full";
1602
+ } else if (decodeResult.remaining.text.length > 0) {
1603
+ processChecksum(decodeResult, checksum);
1604
+ decodeResult.decoded = true;
1605
+ decodeResult.decoder.decodeLevel = "partial";
1606
+ } else {
1607
+ decodeResult.decoded = false;
1608
+ decodeResult.decoder.decodeLevel = "none";
1609
+ }
1531
1610
  } else if (parts.length === 10) {
1532
- decodeResult.remaining.text = "";
1533
- processPosition(decodeResult, parts[0]);
1534
1611
  processAlt(decodeResult, parts[3]);
1535
1612
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1536
1613
  processTemp(decodeResult, parts[7]);
@@ -1540,8 +1617,6 @@ var Label_H1_POS = class extends DecoderPlugin {
1540
1617
  decodeResult.decoded = true;
1541
1618
  decodeResult.decoder.decodeLevel = "partial";
1542
1619
  } else if (parts.length === 11) {
1543
- decodeResult.remaining.text = "";
1544
- processPosition(decodeResult, parts[0]);
1545
1620
  processAlt(decodeResult, parts[3]);
1546
1621
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1547
1622
  processTemp(decodeResult, parts[7]);
@@ -1550,9 +1625,18 @@ var Label_H1_POS = class extends DecoderPlugin {
1550
1625
  processChecksum(decodeResult, checksum);
1551
1626
  decodeResult.decoded = true;
1552
1627
  decodeResult.decoder.decodeLevel = "partial";
1628
+ } else if (parts.length === 12) {
1629
+ const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1630
+ processUnknown(decodeResult, parts[3]);
1631
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1632
+ processTemp(decodeResult, parts[7]);
1633
+ processUnknown(decodeResult, parts[8]);
1634
+ processUnknown(decodeResult, parts[9]);
1635
+ processUnknown(decodeResult, parts[10]);
1636
+ processChecksum(decodeResult, checksum);
1637
+ decodeResult.decoded = true;
1638
+ decodeResult.decoder.decodeLevel = "partial";
1553
1639
  } else if (parts.length === 14) {
1554
- decodeResult.remaining.text = "";
1555
- processPosition(decodeResult, parts[0]);
1556
1640
  processAlt(decodeResult, parts[3]);
1557
1641
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1558
1642
  processTemp(decodeResult, parts[7]);
@@ -1566,8 +1650,6 @@ var Label_H1_POS = class extends DecoderPlugin {
1566
1650
  decodeResult.decoded = true;
1567
1651
  decodeResult.decoder.decodeLevel = "partial";
1568
1652
  } else if (parts.length === 15) {
1569
- decodeResult.remaining.text = "";
1570
- processUnknown(decodeResult, parts[0]);
1571
1653
  processUnknown(decodeResult, parts[1]);
1572
1654
  let date = void 0;
1573
1655
  if (parts[2].startsWith("/DC")) {
@@ -1580,7 +1662,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1580
1662
  for (let i = 0; i < fields.length; ++i) {
1581
1663
  const field = fields[i];
1582
1664
  if (field.startsWith("PS")) {
1583
- processPosition(decodeResult, field.substring(2));
1665
+ processPosition2(decodeResult, field.substring(2));
1584
1666
  } else {
1585
1667
  if (i === 0) {
1586
1668
  processUnknown(decodeResult, field);
@@ -1599,9 +1681,16 @@ var Label_H1_POS = class extends DecoderPlugin {
1599
1681
  processChecksum(decodeResult, checksum);
1600
1682
  decodeResult.decoded = true;
1601
1683
  decodeResult.decoder.decodeLevel = "partial";
1684
+ } else if (parts.length === 21) {
1685
+ processRunway(decodeResult, parts[1]);
1686
+ processUnknown(decodeResult, parts.slice(2, 11).join(","));
1687
+ processTemp(decodeResult, parts[11]);
1688
+ processUnknown(decodeResult, parts.slice(12, 20).join(","));
1689
+ FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1690
+ processChecksum(decodeResult, checksum);
1691
+ decodeResult.decoded = true;
1692
+ decodeResult.decoder.decodeLevel = "partial";
1602
1693
  } else if (parts.length === 32) {
1603
- decodeResult.remaining.text = "";
1604
- processPosition(decodeResult, parts[0]);
1605
1694
  processRunway(decodeResult, parts[1]);
1606
1695
  const time = parts[2];
1607
1696
  processUnknown(decodeResult, parts[3]);
@@ -1626,7 +1715,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1626
1715
  if (options.debug) {
1627
1716
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1628
1717
  }
1629
- decodeResult.remaining.text = message.text;
1718
+ decodeResult.remaining.text += message.text;
1630
1719
  decodeResult.decoded = false;
1631
1720
  decodeResult.decoder.decodeLevel = "none";
1632
1721
  }
@@ -1636,7 +1725,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1636
1725
  function processUnknown(decodeResult, value) {
1637
1726
  decodeResult.remaining.text += "," + value;
1638
1727
  }
1639
- function processPosition(decodeResult, value) {
1728
+ function processPosition2(decodeResult, value) {
1640
1729
  const position = CoordinateUtils.decodeStringCoordinates(value);
1641
1730
  if (position) {
1642
1731
  decodeResult.raw.position = position;
@@ -1667,11 +1756,11 @@ function processTemp(decodeResult, value) {
1667
1756
  });
1668
1757
  }
1669
1758
  function processRunway(decodeResult, value) {
1670
- decodeResult.raw.runway = value.replace("RW", "");
1759
+ decodeResult.raw.arrival_runway = value.replace("RW", "");
1671
1760
  decodeResult.formatted.items.push({
1672
1761
  type: "runway",
1673
- label: "Runway",
1674
- value: decodeResult.raw.runway
1762
+ label: "Arrival Runway",
1763
+ value: decodeResult.raw.arrival_runway
1675
1764
  });
1676
1765
  }
1677
1766
  function processGndspd(decodeResult, value) {
@@ -1684,14 +1773,17 @@ function processGndspd(decodeResult, value) {
1684
1773
  });
1685
1774
  }
1686
1775
  function processRoute(decodeResult, last, time, next, eta, then, date) {
1687
- const lastCoords = CoordinateUtils.decodeStringCoordinates(last);
1688
- const nextCoords = CoordinateUtils.decodeStringCoordinates(next);
1689
1776
  const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1690
1777
  const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1691
1778
  const timeFormat = date ? "epoch" : "tod";
1692
- const lastWaypoint = lastCoords ? { name: "", latitude: lastCoords.latitude, longitude: lastCoords.longitude, time: lastTime, timeFormat } : { name: last, time: lastTime, timeFormat };
1693
- const nextWaypoint = nextCoords ? { name: "", latitude: nextCoords.latitude, longitude: nextCoords.longitude, time: nextTime, timeFormat } : { name: next, time: nextTime, timeFormat };
1694
- const waypoints = [lastWaypoint, nextWaypoint, { name: then || "?" }];
1779
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1780
+ lastWaypoint.time = lastTime;
1781
+ lastWaypoint.timeFormat = timeFormat;
1782
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1783
+ nextWaypoint.time = nextTime;
1784
+ nextWaypoint.timeFormat = timeFormat;
1785
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1786
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1695
1787
  decodeResult.raw.route = { waypoints };
1696
1788
  decodeResult.formatted.items.push({
1697
1789
  type: "aircraft_route",
@@ -1709,6 +1801,14 @@ function processChecksum(decodeResult, value) {
1709
1801
  value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1710
1802
  });
1711
1803
  }
1804
+ function findHeader(text) {
1805
+ const parts = text.split(",");
1806
+ const header = parts[0];
1807
+ if (header.indexOf("/TS") === -1) {
1808
+ return header;
1809
+ }
1810
+ return parts[0] + "," + parts[1];
1811
+ }
1712
1812
 
1713
1813
  // lib/plugins/Label_H1_WRN.ts
1714
1814
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -2047,7 +2147,7 @@ var Label_QQ = class extends DecoderPlugin {
2047
2147
 
2048
2148
  // lib/utils/miam.ts
2049
2149
  var Base85 = __toESM(require("base85"));
2050
- var Zlib = __toESM(require("zlib"));
2150
+ var zlib = __toESM(require("minizlib"));
2051
2151
  var MIAMCoreV1CRCLength = 4;
2052
2152
  var MIAMCoreV2CRCLength = 2;
2053
2153
  var MIAMCoreUtils = class {
@@ -2757,7 +2857,10 @@ var MIAMCoreUtils = class {
2757
2857
  if (body !== void 0 && body.length > 0) {
2758
2858
  if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
2759
2859
  try {
2760
- pduData = Zlib.inflateRawSync(body, { windowBits: 15 });
2860
+ const decompress = new zlib.InflateRaw({ windowBits: 15 });
2861
+ decompress.write(body);
2862
+ decompress.flush(zlib.constants.Z_SYNC_FLUSH);
2863
+ pduData = decompress.read();
2761
2864
  } catch (e) {
2762
2865
  pduErrors.push("Inflation failed for body: " + e);
2763
2866
  }