@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.mjs CHANGED
@@ -1203,12 +1203,19 @@ var RouteUtils = class _RouteUtils {
1203
1203
  if (waypoint.latitude && waypoint.longitude) {
1204
1204
  s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
1205
1205
  }
1206
+ if (waypoint.offset) {
1207
+ s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
1208
+ }
1206
1209
  if (waypoint.time && waypoint.timeFormat) {
1207
1210
  s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
1208
1211
  }
1209
1212
  return s;
1210
1213
  }
1211
1214
  static getWaypoint(leg) {
1215
+ const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
1216
+ if (regex?.length == 4) {
1217
+ return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
1218
+ }
1212
1219
  const waypoint = leg.split(",");
1213
1220
  if (waypoint.length == 2) {
1214
1221
  const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
@@ -1216,10 +1223,11 @@ var RouteUtils = class _RouteUtils {
1216
1223
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1217
1224
  }
1218
1225
  }
1219
- if (leg.length == 14) {
1226
+ if (leg.length == 13 || leg.length == 14) {
1220
1227
  const position = CoordinateUtils.decodeStringCoordinates(leg);
1228
+ const name = waypoint.length == 2 ? waypoint[0] : "";
1221
1229
  if (position) {
1222
- return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1230
+ return { name, latitude: position.latitude, longitude: position.longitude };
1223
1231
  }
1224
1232
  }
1225
1233
  return { name: leg };
@@ -1280,7 +1288,7 @@ var FlightPlanUtils = class {
1280
1288
  addRoute(decodeResult, value);
1281
1289
  break;
1282
1290
  case "R":
1283
- addDepartureRunway(decodeResult, value);
1291
+ addRunway(decodeResult, value);
1284
1292
  break;
1285
1293
  default:
1286
1294
  if (allKnownFields) {
@@ -1294,41 +1302,106 @@ var FlightPlanUtils = class {
1294
1302
  return allKnownFields;
1295
1303
  }
1296
1304
  };
1305
+ function parseMessageType(decodeResult, messageType) {
1306
+ let decoded = true;
1307
+ const parts = messageType.split("#");
1308
+ if (parts.length == 1) {
1309
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1310
+ decoded = processPosition(decodeResult, parts[0].substring(3));
1311
+ }
1312
+ return decoded;
1313
+ } else if (parts.length == 2) {
1314
+ if (parts[0].length > 0) {
1315
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1316
+ decodeResult.raw.flight_number = parts[0].substring(3);
1317
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1318
+ }
1319
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1320
+ decoded = processPosition(decodeResult, parts[1].substring(6));
1321
+ }
1322
+ decodeResult.raw.message_type = messageType;
1323
+ return decoded;
1324
+ }
1325
+ decodeResult.remaining.text += messageType;
1326
+ return false;
1327
+ }
1297
1328
  function parseHeader(decodeResult, header) {
1298
1329
  let allKnownFields = true;
1299
1330
  const fields = header.split("/");
1300
- for (let i = 1; i < fields.length - 1; ++i) {
1331
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1332
+ for (let i = 1; i < fields.length; ++i) {
1301
1333
  if (fields[i].startsWith("FN")) {
1302
1334
  decodeResult.raw.flight_number = fields[i].substring(2);
1303
1335
  } else if (fields[i].startsWith("SN")) {
1304
1336
  decodeResult.raw.serial_number = fields[i].substring(2);
1305
1337
  } else if (fields[i].startsWith("TS")) {
1306
1338
  const ts = fields[i].substring(2).split(",");
1307
- decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1339
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1340
+ if (Number.isNaN(time)) {
1341
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1342
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1343
+ }
1344
+ decodeResult.raw.message_timestamp = time;
1345
+ } else if (fields[i].startsWith("PS")) {
1346
+ const pos = fields[i].substring(2);
1347
+ allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1348
+ } else if (fields[i].startsWith("DT")) {
1349
+ const icao = fields[i].substring(2);
1350
+ decodeResult.raw.arrival_icao = icao;
1351
+ decodeResult.formatted.items.push({
1352
+ type: "destination",
1353
+ code: "DST",
1354
+ label: "Destination",
1355
+ value: decodeResult.raw.arrival_icao
1356
+ });
1357
+ } else if (fields[i].startsWith("RF")) {
1358
+ decodeResult.formatted.items.push({
1359
+ type: "status",
1360
+ code: "ROUTE_STATUS",
1361
+ label: "Route Status",
1362
+ value: "Route Filed"
1363
+ });
1364
+ decodeResult.raw.route_status = "RF";
1365
+ if (fields[i].length > 2) {
1366
+ addRoute(decodeResult, fields[i].substring(2));
1367
+ }
1368
+ } else if (fields[i] == "RP") {
1369
+ decodeResult.raw.route_status = "RP";
1370
+ decodeResult.formatted.items.push({
1371
+ type: "status",
1372
+ code: "ROUTE_STATUS",
1373
+ label: "Route Status",
1374
+ value: "Route Planned"
1375
+ });
1376
+ decodeResult.raw.route_status = fields[i];
1377
+ } else if (fields[i] == "RI") {
1378
+ decodeResult.raw.route_status = "RI";
1379
+ decodeResult.formatted.items.push({
1380
+ type: "status",
1381
+ code: "ROUTE_STATUS",
1382
+ label: "Route Status",
1383
+ value: "Route Inactive"
1384
+ });
1308
1385
  } else {
1309
1386
  decodeResult.remaining.text += "/" + fields[i];
1310
1387
  allKnownFields = false;
1311
1388
  }
1312
1389
  }
1313
- decodeResult.raw.route_status = fields[fields.length - 1];
1314
- var text;
1315
- if (decodeResult.raw.route_status == "RP") {
1316
- text = "Route Planned";
1317
- } else if (decodeResult.raw.route_status == "RI") {
1318
- text = "Route Inactive";
1319
- } else if (decodeResult.raw.route_status == "RF") {
1320
- text = "Route Filed";
1321
- } else {
1322
- text = decodeResult.raw.route_status;
1323
- }
1324
- decodeResult.formatted.items.push({
1325
- type: "status",
1326
- code: "ROUTE_STATUS",
1327
- label: "Route Status",
1328
- value: text
1329
- });
1330
1390
  return allKnownFields;
1331
1391
  }
1392
+ function processPosition(decodeResult, value) {
1393
+ const position = CoordinateUtils.decodeStringCoordinates(value);
1394
+ if (position) {
1395
+ decodeResult.raw.position = position;
1396
+ decodeResult.formatted.items.push({
1397
+ type: "aircraft_position",
1398
+ code: "POS",
1399
+ label: "Aircraft Position",
1400
+ value: CoordinateUtils.coordinateString(position)
1401
+ });
1402
+ }
1403
+ return !!position;
1404
+ }
1332
1405
  function addArrivalAirport(decodeResult, value) {
1333
1406
  decodeResult.raw.arrival_icao = value;
1334
1407
  decodeResult.formatted.items.push({
@@ -1347,12 +1420,20 @@ function addDepartureAirport(decodeResult, value) {
1347
1420
  value: decodeResult.raw.departure_icao
1348
1421
  });
1349
1422
  }
1350
- function addDepartureRunway(decodeResult, value) {
1351
- decodeResult.raw.runway = value;
1423
+ function addRunway(decodeResult, value) {
1424
+ if (value.length === 8) {
1425
+ decodeResult.raw.arrival_runway = value.substring(4, 7);
1426
+ decodeResult.formatted.items.push({
1427
+ type: "runway",
1428
+ label: "Arrival Runway",
1429
+ value: decodeResult.raw.arrival_runway
1430
+ });
1431
+ }
1432
+ decodeResult.raw.departure_runway = value.substring(0, 3);
1352
1433
  decodeResult.formatted.items.push({
1353
1434
  type: "runway",
1354
- label: "Runway",
1355
- value: decodeResult.raw.runway
1435
+ label: "Departure Runway",
1436
+ value: decodeResult.raw.departure_runway
1356
1437
  });
1357
1438
  }
1358
1439
  function addRoute(decodeResult, value) {
@@ -1462,7 +1543,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1462
1543
  qualifiers() {
1463
1544
  return {
1464
1545
  labels: ["H1"],
1465
- preambles: ["POS", "#M1BPOS"]
1546
+ preambles: ["POS", "#M1BPOS", "/.POS"]
1466
1547
  //TODO - support data before #
1467
1548
  };
1468
1549
  }
@@ -1471,29 +1552,25 @@ var Label_H1_POS = class extends DecoderPlugin {
1471
1552
  decodeResult.decoder.name = this.name;
1472
1553
  decodeResult.formatted.description = "Position Report";
1473
1554
  decodeResult.message = message;
1555
+ decodeResult.remaining.text = "";
1474
1556
  const checksum = message.text.slice(-4);
1475
- const parts = message.text.replace("#M1B", "").replace("POS", "").slice(0, -4).split(",");
1476
- if (parts.length == 1 && parts[0].startsWith("/RF")) {
1477
- decodeResult.raw.route_status == "RF";
1478
- decodeResult.formatted.items.push({
1479
- type: "status",
1480
- code: "ROUTE_STATUS",
1481
- label: "Route Status",
1482
- value: "Route Filed"
1483
- });
1484
- decodeResult.raw.route = { waypoints: parts[0].substring(3, parts[0].length).split(".").map((leg) => RouteUtils.getWaypoint(leg)) };
1485
- decodeResult.formatted.items.push({
1486
- type: "aircraft_route",
1487
- code: "ROUTE",
1488
- label: "Aircraft Route",
1489
- value: RouteUtils.routeToString(decodeResult.raw.route)
1490
- });
1491
- processChecksum(decodeResult, checksum);
1492
- decodeResult.decoded = true;
1493
- decodeResult.decoder.decodeLevel = "full";
1557
+ const header = findHeader(message.text.slice(0, -4));
1558
+ const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1559
+ const parts = message.text.replace(header, "").slice(0, -4).split(",");
1560
+ if (parts.length == 1) {
1561
+ if (decoded) {
1562
+ processChecksum(decodeResult, checksum);
1563
+ decodeResult.decoded = true;
1564
+ decodeResult.decoder.decodeLevel = "full";
1565
+ } else if (decodeResult.remaining.text.length > 0) {
1566
+ processChecksum(decodeResult, checksum);
1567
+ decodeResult.decoded = true;
1568
+ decodeResult.decoder.decodeLevel = "partial";
1569
+ } else {
1570
+ decodeResult.decoded = false;
1571
+ decodeResult.decoder.decodeLevel = "none";
1572
+ }
1494
1573
  } else if (parts.length === 10) {
1495
- decodeResult.remaining.text = "";
1496
- processPosition(decodeResult, parts[0]);
1497
1574
  processAlt(decodeResult, parts[3]);
1498
1575
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1499
1576
  processTemp(decodeResult, parts[7]);
@@ -1503,8 +1580,6 @@ var Label_H1_POS = class extends DecoderPlugin {
1503
1580
  decodeResult.decoded = true;
1504
1581
  decodeResult.decoder.decodeLevel = "partial";
1505
1582
  } else if (parts.length === 11) {
1506
- decodeResult.remaining.text = "";
1507
- processPosition(decodeResult, parts[0]);
1508
1583
  processAlt(decodeResult, parts[3]);
1509
1584
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1510
1585
  processTemp(decodeResult, parts[7]);
@@ -1513,9 +1588,18 @@ var Label_H1_POS = class extends DecoderPlugin {
1513
1588
  processChecksum(decodeResult, checksum);
1514
1589
  decodeResult.decoded = true;
1515
1590
  decodeResult.decoder.decodeLevel = "partial";
1591
+ } else if (parts.length === 12) {
1592
+ const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1593
+ processUnknown(decodeResult, parts[3]);
1594
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1595
+ processTemp(decodeResult, parts[7]);
1596
+ processUnknown(decodeResult, parts[8]);
1597
+ processUnknown(decodeResult, parts[9]);
1598
+ processUnknown(decodeResult, parts[10]);
1599
+ processChecksum(decodeResult, checksum);
1600
+ decodeResult.decoded = true;
1601
+ decodeResult.decoder.decodeLevel = "partial";
1516
1602
  } else if (parts.length === 14) {
1517
- decodeResult.remaining.text = "";
1518
- processPosition(decodeResult, parts[0]);
1519
1603
  processAlt(decodeResult, parts[3]);
1520
1604
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1521
1605
  processTemp(decodeResult, parts[7]);
@@ -1529,8 +1613,6 @@ var Label_H1_POS = class extends DecoderPlugin {
1529
1613
  decodeResult.decoded = true;
1530
1614
  decodeResult.decoder.decodeLevel = "partial";
1531
1615
  } else if (parts.length === 15) {
1532
- decodeResult.remaining.text = "";
1533
- processUnknown(decodeResult, parts[0]);
1534
1616
  processUnknown(decodeResult, parts[1]);
1535
1617
  let date = void 0;
1536
1618
  if (parts[2].startsWith("/DC")) {
@@ -1543,7 +1625,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1543
1625
  for (let i = 0; i < fields.length; ++i) {
1544
1626
  const field = fields[i];
1545
1627
  if (field.startsWith("PS")) {
1546
- processPosition(decodeResult, field.substring(2));
1628
+ processPosition2(decodeResult, field.substring(2));
1547
1629
  } else {
1548
1630
  if (i === 0) {
1549
1631
  processUnknown(decodeResult, field);
@@ -1562,9 +1644,16 @@ var Label_H1_POS = class extends DecoderPlugin {
1562
1644
  processChecksum(decodeResult, checksum);
1563
1645
  decodeResult.decoded = true;
1564
1646
  decodeResult.decoder.decodeLevel = "partial";
1647
+ } else if (parts.length === 21) {
1648
+ processRunway(decodeResult, parts[1]);
1649
+ processUnknown(decodeResult, parts.slice(2, 11).join(","));
1650
+ processTemp(decodeResult, parts[11]);
1651
+ processUnknown(decodeResult, parts.slice(12, 20).join(","));
1652
+ FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1653
+ processChecksum(decodeResult, checksum);
1654
+ decodeResult.decoded = true;
1655
+ decodeResult.decoder.decodeLevel = "partial";
1565
1656
  } else if (parts.length === 32) {
1566
- decodeResult.remaining.text = "";
1567
- processPosition(decodeResult, parts[0]);
1568
1657
  processRunway(decodeResult, parts[1]);
1569
1658
  const time = parts[2];
1570
1659
  processUnknown(decodeResult, parts[3]);
@@ -1589,7 +1678,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1589
1678
  if (options.debug) {
1590
1679
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1591
1680
  }
1592
- decodeResult.remaining.text = message.text;
1681
+ decodeResult.remaining.text += message.text;
1593
1682
  decodeResult.decoded = false;
1594
1683
  decodeResult.decoder.decodeLevel = "none";
1595
1684
  }
@@ -1599,7 +1688,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1599
1688
  function processUnknown(decodeResult, value) {
1600
1689
  decodeResult.remaining.text += "," + value;
1601
1690
  }
1602
- function processPosition(decodeResult, value) {
1691
+ function processPosition2(decodeResult, value) {
1603
1692
  const position = CoordinateUtils.decodeStringCoordinates(value);
1604
1693
  if (position) {
1605
1694
  decodeResult.raw.position = position;
@@ -1630,11 +1719,11 @@ function processTemp(decodeResult, value) {
1630
1719
  });
1631
1720
  }
1632
1721
  function processRunway(decodeResult, value) {
1633
- decodeResult.raw.runway = value.replace("RW", "");
1722
+ decodeResult.raw.arrival_runway = value.replace("RW", "");
1634
1723
  decodeResult.formatted.items.push({
1635
1724
  type: "runway",
1636
- label: "Runway",
1637
- value: decodeResult.raw.runway
1725
+ label: "Arrival Runway",
1726
+ value: decodeResult.raw.arrival_runway
1638
1727
  });
1639
1728
  }
1640
1729
  function processGndspd(decodeResult, value) {
@@ -1647,14 +1736,17 @@ function processGndspd(decodeResult, value) {
1647
1736
  });
1648
1737
  }
1649
1738
  function processRoute(decodeResult, last, time, next, eta, then, date) {
1650
- const lastCoords = CoordinateUtils.decodeStringCoordinates(last);
1651
- const nextCoords = CoordinateUtils.decodeStringCoordinates(next);
1652
1739
  const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1653
1740
  const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1654
1741
  const timeFormat = date ? "epoch" : "tod";
1655
- const lastWaypoint = lastCoords ? { name: "", latitude: lastCoords.latitude, longitude: lastCoords.longitude, time: lastTime, timeFormat } : { name: last, time: lastTime, timeFormat };
1656
- const nextWaypoint = nextCoords ? { name: "", latitude: nextCoords.latitude, longitude: nextCoords.longitude, time: nextTime, timeFormat } : { name: next, time: nextTime, timeFormat };
1657
- const waypoints = [lastWaypoint, nextWaypoint, { name: then || "?" }];
1742
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1743
+ lastWaypoint.time = lastTime;
1744
+ lastWaypoint.timeFormat = timeFormat;
1745
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1746
+ nextWaypoint.time = nextTime;
1747
+ nextWaypoint.timeFormat = timeFormat;
1748
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1749
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1658
1750
  decodeResult.raw.route = { waypoints };
1659
1751
  decodeResult.formatted.items.push({
1660
1752
  type: "aircraft_route",
@@ -1672,6 +1764,14 @@ function processChecksum(decodeResult, value) {
1672
1764
  value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1673
1765
  });
1674
1766
  }
1767
+ function findHeader(text) {
1768
+ const parts = text.split(",");
1769
+ const header = parts[0];
1770
+ if (header.indexOf("/TS") === -1) {
1771
+ return header;
1772
+ }
1773
+ return parts[0] + "," + parts[1];
1774
+ }
1675
1775
 
1676
1776
  // lib/plugins/Label_H1_WRN.ts
1677
1777
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -2010,7 +2110,7 @@ var Label_QQ = class extends DecoderPlugin {
2010
2110
 
2011
2111
  // lib/utils/miam.ts
2012
2112
  import * as Base85 from "base85";
2013
- import * as Zlib from "zlib";
2113
+ import * as zlib from "minizlib";
2014
2114
  var MIAMCoreV1CRCLength = 4;
2015
2115
  var MIAMCoreV2CRCLength = 2;
2016
2116
  var MIAMCoreUtils = class {
@@ -2720,7 +2820,10 @@ var MIAMCoreUtils = class {
2720
2820
  if (body !== void 0 && body.length > 0) {
2721
2821
  if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
2722
2822
  try {
2723
- pduData = Zlib.inflateRawSync(body, { windowBits: 15 });
2823
+ const decompress = new zlib.InflateRaw({ windowBits: 15 });
2824
+ decompress.write(body);
2825
+ decompress.flush(zlib.constants.Z_SYNC_FLUSH);
2826
+ pduData = decompress.read();
2724
2827
  } catch (e) {
2725
2828
  pduErrors.push("Inflation failed for body: " + e);
2726
2829
  }