@airframes/acars-decoder 1.6.7 → 1.6.9

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
@@ -208,6 +208,12 @@ var Label_5Z = class extends DecoderPlugin {
208
208
 
209
209
  // lib/utils/coordinate_utils.ts
210
210
  var CoordinateUtils = class {
211
+ /**
212
+ * Decode a string of coordinates into an object with latitude and longitude in millidegrees
213
+ * @param stringCoords - The string of coordinates to decode
214
+ *
215
+ * @returns An object with latitude and longitude properties
216
+ */
211
217
  static decodeStringCoordinates(stringCoords) {
212
218
  var results = {};
213
219
  const firstChar = stringCoords.substring(0, 1);
@@ -225,6 +231,33 @@ var CoordinateUtils = class {
225
231
  }
226
232
  return results;
227
233
  }
234
+ /**
235
+ * Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
236
+ * @param stringCoords - The string of coordinates to decode
237
+ *
238
+ * @returns An object with latitude and longitude properties
239
+ */
240
+ static decodeStringCoordinatesDecimalMinutes(stringCoords) {
241
+ var results = {};
242
+ const firstChar = stringCoords.substring(0, 1);
243
+ let middleChar = stringCoords.substring(6, 7);
244
+ let longitudeChars = stringCoords.substring(7, 13);
245
+ if (middleChar == " ") {
246
+ middleChar = stringCoords.substring(7, 8);
247
+ longitudeChars = stringCoords.substring(8, 14);
248
+ }
249
+ const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
250
+ const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
251
+ const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
252
+ const lonMin = Number(longitudeChars) % 1e3 / 10;
253
+ if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
254
+ results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
255
+ results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
256
+ } else {
257
+ return;
258
+ }
259
+ return results;
260
+ }
228
261
  static coordinateString(coords) {
229
262
  const latDir = coords.latitude > 0 ? "N" : "S";
230
263
  const lonDir = coords.longitude > 0 ? "E" : "W";
@@ -595,6 +628,96 @@ var Label_20_POS = class extends DecoderPlugin {
595
628
  }
596
629
  };
597
630
 
631
+ // lib/plugins/Label_21_POS.ts
632
+ var Label_21_POS = class extends DecoderPlugin {
633
+ name = "label-21-pos";
634
+ qualifiers() {
635
+ return {
636
+ labels: ["21"],
637
+ preambles: ["POS"]
638
+ };
639
+ }
640
+ decode(message, options = {}) {
641
+ const decodeResult = this.defaultResult();
642
+ decodeResult.decoder.name = this.name;
643
+ decodeResult.formatted.description = "Position Report";
644
+ decodeResult.message = message;
645
+ decodeResult.raw.preamble = message.text.substring(0, 3);
646
+ const content = message.text.substring(3);
647
+ console.log("Content: " + content);
648
+ const fields = content.split(",");
649
+ console.log("Field Count: " + fields.length);
650
+ if (fields.length == 9) {
651
+ processPosition(decodeResult, fields[0].trim());
652
+ processAlt(decodeResult, fields[3]);
653
+ processTemp(decodeResult, fields[6]);
654
+ processArrvApt(decodeResult, fields[8]);
655
+ decodeResult.raw.remaining = [
656
+ fields[1],
657
+ fields[2],
658
+ fields[4],
659
+ fields[5],
660
+ fields[7]
661
+ ].join(",");
662
+ decodeResult.decoded = true;
663
+ decodeResult.decoder.decodeLevel = "partial";
664
+ } else {
665
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
666
+ decodeResult.decoded = false;
667
+ decodeResult.decoder.decodeLevel = "none";
668
+ }
669
+ return decodeResult;
670
+ }
671
+ };
672
+ function processPosition(decodeResult, value) {
673
+ if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
674
+ return false;
675
+ }
676
+ const latDir = value[0] === "N" ? 1 : -1;
677
+ const lonDir = value[8] === "E" ? 1 : -1;
678
+ const position = {
679
+ latitude: latDir * Number(value.substring(1, 7)),
680
+ longitude: lonDir * Number(value.substring(9, 15))
681
+ };
682
+ if (position) {
683
+ decodeResult.raw.position = position;
684
+ decodeResult.formatted.items.push({
685
+ type: "aircraft_position",
686
+ code: "POS",
687
+ label: "Aircraft Position",
688
+ value: CoordinateUtils.coordinateString(position)
689
+ });
690
+ }
691
+ return !!position;
692
+ }
693
+ function processAlt(decodeResult, value) {
694
+ decodeResult.raw.altitude = Number(value);
695
+ decodeResult.formatted.items.push({
696
+ type: "altitude",
697
+ code: "ALT",
698
+ label: "Altitude",
699
+ value: `${decodeResult.raw.altitude} feet`
700
+ });
701
+ }
702
+ function processTemp(decodeResult, value) {
703
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
704
+ decodeResult.formatted.items.push({
705
+ type: "outside_air_temperature",
706
+ code: "OATEMP",
707
+ label: "Outside Air Temperature (C)",
708
+ value: `${decodeResult.raw.outside_air_temperature}`
709
+ });
710
+ }
711
+ function processArrvApt(decodeResult, value) {
712
+ decodeResult.raw.arrival_icao = value;
713
+ decodeResult.formatted.items.push({
714
+ type: "destination",
715
+ code: "DST",
716
+ label: "Destination",
717
+ value: decodeResult.raw.arrival_icao
718
+ });
719
+ }
720
+
598
721
  // lib/plugins/Label_30_Slash_EA.ts
599
722
  var Label_30_Slash_EA = class extends DecoderPlugin {
600
723
  name = "label-30-slash-ea";
@@ -892,7 +1015,7 @@ var Label_44_POS = class extends DecoderPlugin {
892
1015
  console.log(`Label 44 Position Report: groups`);
893
1016
  console.log(results.groups);
894
1017
  }
895
- decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
1018
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
896
1019
  decodeResult.raw.flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? "0" : Number(results.groups.flight_level_or_ground);
897
1020
  decodeResult.raw.departure_icao = results.groups.departure_icao;
898
1021
  decodeResult.raw.arrival_icao = results.groups.arrival_icao;
@@ -907,9 +1030,9 @@ var Label_44_POS = class extends DecoderPlugin {
907
1030
  }
908
1031
  if (decodeResult.raw.position) {
909
1032
  decodeResult.formatted.items.push({
910
- type: "position",
1033
+ type: "aircraft_position",
911
1034
  code: "POS",
912
- label: "Position",
1035
+ label: "Aircraft Position",
913
1036
  value: CoordinateUtils.coordinateString(decodeResult.raw.position)
914
1037
  });
915
1038
  }
@@ -1217,6 +1340,168 @@ var Label_ColonComma = class extends DecoderPlugin {
1217
1340
  }
1218
1341
  };
1219
1342
 
1343
+ // lib/plugins/Label_H1_FLR.ts
1344
+ var Label_H1_FLR = class extends DecoderPlugin {
1345
+ name = "label-h1-flr";
1346
+ qualifiers() {
1347
+ return {
1348
+ labels: ["H1"],
1349
+ preambles: ["FLR", "#CFBFLR"]
1350
+ };
1351
+ }
1352
+ decode(message, options = {}) {
1353
+ let decodeResult = this.defaultResult();
1354
+ decodeResult.decoder.name = this.name;
1355
+ decodeResult.formatted.description = "Fault Log Report";
1356
+ decodeResult.message = message;
1357
+ const parts = message.text.split("/FR");
1358
+ if (parts.length > 1) {
1359
+ decodeResult.remaining.text = "";
1360
+ const fields = parts[0].split("/");
1361
+ for (let i = 1; i < fields.length; i++) {
1362
+ const field = fields[i];
1363
+ if (field.startsWith("PN")) {
1364
+ processUnknown(decodeResult, "/" + field);
1365
+ } else {
1366
+ processUnknown(decodeResult, "/" + field);
1367
+ }
1368
+ }
1369
+ const data = parts[1].substring(0, 20);
1370
+ const msg = parts[1].substring(20);
1371
+ const datetime = data.substring(0, 12);
1372
+ const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
1373
+ processUnknown(decodeResult, data.substring(12));
1374
+ decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
1375
+ decodeResult.raw.fault_message = msg;
1376
+ decodeResult.formatted.items.push({
1377
+ type: "fault",
1378
+ code: "FR",
1379
+ label: "Fault Report",
1380
+ value: decodeResult.raw.fault_message
1381
+ });
1382
+ decodeResult.decoded = true;
1383
+ decodeResult.decoder.decodeLevel = "partial";
1384
+ } else {
1385
+ if (options.debug) {
1386
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
1387
+ }
1388
+ decodeResult.remaining.text = message.text;
1389
+ decodeResult.decoded = false;
1390
+ decodeResult.decoder.decodeLevel = "none";
1391
+ }
1392
+ return decodeResult;
1393
+ }
1394
+ };
1395
+ function processUnknown(decodeResult, value) {
1396
+ decodeResult.remaining.text += value;
1397
+ }
1398
+
1399
+ // lib/utils/result_formatter.ts
1400
+ var ResultFormatter = class {
1401
+ static altitude(decodeResult, value) {
1402
+ decodeResult.raw.altitude = value;
1403
+ decodeResult.formatted.items.push({
1404
+ type: "altitude",
1405
+ code: "ALT",
1406
+ label: "Altitude",
1407
+ value: `${decodeResult.raw.altitude} feet`
1408
+ });
1409
+ }
1410
+ static flightNumber(decodeResult, value) {
1411
+ decodeResult.raw.flight_number = value;
1412
+ }
1413
+ static departureAirport(decodeResult, value) {
1414
+ decodeResult.raw.departure_icao = value;
1415
+ decodeResult.formatted.items.push({
1416
+ type: "origin",
1417
+ code: "ORG",
1418
+ label: "Origin",
1419
+ value: decodeResult.raw.departure_icao
1420
+ });
1421
+ }
1422
+ static departureRunway(decodeResult, value) {
1423
+ decodeResult.raw.departure_runway = value;
1424
+ decodeResult.formatted.items.push({
1425
+ type: "runway",
1426
+ code: "DEPRWY",
1427
+ label: "Departure Runway",
1428
+ value: decodeResult.raw.departure_runway
1429
+ });
1430
+ }
1431
+ static arrivalAirport(decodeResult, value) {
1432
+ decodeResult.raw.arrival_icao = value;
1433
+ decodeResult.formatted.items.push({
1434
+ type: "destination",
1435
+ code: "DST",
1436
+ label: "Destination",
1437
+ value: decodeResult.raw.arrival_icao
1438
+ });
1439
+ }
1440
+ static eta(decodeResult, value) {
1441
+ decodeResult.formatted.items.push({
1442
+ type: "eta",
1443
+ code: "ETA",
1444
+ label: "Estimated Time of Arrival",
1445
+ value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
1446
+ });
1447
+ }
1448
+ static arrivalRunway(decodeResult, value) {
1449
+ decodeResult.raw.arrival_runway = value;
1450
+ decodeResult.formatted.items.push({
1451
+ type: "runway",
1452
+ label: "Arrival Runway",
1453
+ value: decodeResult.raw.arrival_runway
1454
+ });
1455
+ }
1456
+ static currentFuel(decodeResult, value) {
1457
+ decodeResult.raw.fuel_on_board = value;
1458
+ decodeResult.formatted.items.push({
1459
+ type: "fuel_on_board",
1460
+ code: "FOB",
1461
+ label: "Fuel On Board",
1462
+ value: decodeResult.raw.fuel_on_board.toString()
1463
+ });
1464
+ }
1465
+ static remainingFuel(decodeResult, value) {
1466
+ decodeResult.raw.fuel_remaining = value;
1467
+ decodeResult.formatted.items.push({
1468
+ type: "fuel_remaining",
1469
+ label: "Fuel Remaining",
1470
+ value: decodeResult.raw.fuel_remaining.toString()
1471
+ });
1472
+ }
1473
+ static checksum(decodeResult, value) {
1474
+ decodeResult.raw.checksum = Number("0x" + value);
1475
+ decodeResult.formatted.items.push({
1476
+ type: "message_checksum",
1477
+ code: "CHECKSUM",
1478
+ label: "Message Checksum",
1479
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1480
+ });
1481
+ }
1482
+ static groundspeed(decodeResult, value) {
1483
+ decodeResult.raw.groundspeed = value;
1484
+ decodeResult.formatted.items.push({
1485
+ type: "aircraft_groundspeed",
1486
+ code: "GSPD",
1487
+ label: "Aircraft Groundspeed",
1488
+ value: `${decodeResult.raw.groundspeed}`
1489
+ });
1490
+ }
1491
+ static temperature(decodeResult, value) {
1492
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1493
+ decodeResult.formatted.items.push({
1494
+ type: "outside_air_temperature",
1495
+ code: "OATEMP",
1496
+ label: "Outside Air Temperature (C)",
1497
+ value: `${decodeResult.raw.outside_air_temperature}`
1498
+ });
1499
+ }
1500
+ static unknown(decodeResult, value) {
1501
+ decodeResult.remaining.text += "," + value;
1502
+ }
1503
+ };
1504
+
1220
1505
  // lib/utils/route_utils.ts
1221
1506
  var RouteUtils = class _RouteUtils {
1222
1507
  static routeToString(route) {
@@ -1257,13 +1542,13 @@ var RouteUtils = class _RouteUtils {
1257
1542
  }
1258
1543
  const waypoint = leg.split(",");
1259
1544
  if (waypoint.length == 2) {
1260
- const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1545
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
1261
1546
  if (position) {
1262
1547
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1263
1548
  }
1264
1549
  }
1265
1550
  if (leg.length == 13 || leg.length == 14) {
1266
- const position = CoordinateUtils.decodeStringCoordinates(leg);
1551
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
1267
1552
  const name = waypoint.length == 2 ? waypoint[0] : "";
1268
1553
  if (position) {
1269
1554
  return { name, latitude: position.latitude, longitude: position.longitude };
@@ -1342,146 +1627,52 @@ var FlightPlanUtils = class _FlightPlanUtils {
1342
1627
  }
1343
1628
  static parseHeader(decodeResult, header) {
1344
1629
  let allKnownFields = true;
1345
- const fields = header.split("/");
1346
- allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1347
- for (let i = 1; i < fields.length; ++i) {
1348
- if (fields[i].startsWith("FN")) {
1349
- decodeResult.raw.flight_number = fields[i].substring(2);
1350
- } else if (fields[i].startsWith("SN")) {
1351
- decodeResult.raw.serial_number = fields[i].substring(2);
1352
- } else if (fields[i].startsWith("TS")) {
1353
- const ts = fields[i].substring(2).split(",");
1354
- let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1355
- if (Number.isNaN(time)) {
1356
- const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1357
- time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1358
- }
1359
- decodeResult.raw.message_timestamp = time;
1360
- } else if (fields[i].startsWith("PS")) {
1361
- const pos = fields[i].substring(2);
1362
- allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1363
- } else if (fields[i].startsWith("DT")) {
1364
- const icao = fields[i].substring(2);
1365
- decodeResult.raw.arrival_icao = icao;
1366
- decodeResult.formatted.items.push({
1367
- type: "destination",
1368
- code: "DST",
1369
- label: "Destination",
1370
- value: decodeResult.raw.arrival_icao
1371
- });
1372
- } else if (fields[i].startsWith("ID")) {
1373
- const tail = fields[i].substring(2);
1374
- decodeResult.raw.tail = tail;
1375
- decodeResult.formatted.items.push({
1376
- type: "tail",
1377
- label: "Tail",
1378
- value: decodeResult.raw.tail
1379
- });
1380
- } else if (fields[i].startsWith("RF")) {
1381
- decodeResult.formatted.items.push({
1382
- type: "status",
1383
- code: "ROUTE_STATUS",
1384
- label: "Route Status",
1385
- value: "Route Filed"
1386
- });
1387
- decodeResult.raw.route_status = "RF";
1388
- if (fields[i].length > 2) {
1389
- addRoute(decodeResult, fields[i].substring(2));
1390
- }
1391
- } else if (fields[i] == "RP") {
1392
- decodeResult.raw.route_status = "RP";
1393
- decodeResult.formatted.items.push({
1394
- type: "status",
1395
- code: "ROUTE_STATUS",
1396
- label: "Route Status",
1397
- value: "Route Planned"
1398
- });
1399
- decodeResult.raw.route_status = fields[i];
1400
- } else if (fields[i] == "RI") {
1401
- decodeResult.raw.route_status = "RI";
1402
- decodeResult.formatted.items.push({
1403
- type: "status",
1404
- code: "ROUTE_STATUS",
1405
- label: "Route Status",
1406
- value: "Route Inactive"
1407
- });
1408
- } else {
1409
- decodeResult.remaining.text += "/" + fields[i];
1410
- allKnownFields = false;
1630
+ if (header.startsWith("RF")) {
1631
+ decodeResult.formatted.items.push({
1632
+ type: "status",
1633
+ code: "ROUTE_STATUS",
1634
+ label: "Route Status",
1635
+ value: "Route Filed"
1636
+ });
1637
+ decodeResult.raw.route_status = "RF";
1638
+ if (header.length > 2) {
1639
+ addRoute(decodeResult, header.substring(2));
1411
1640
  }
1641
+ } else if (header.startsWith("RP")) {
1642
+ decodeResult.raw.route_status = "RP";
1643
+ decodeResult.formatted.items.push({
1644
+ type: "status",
1645
+ code: "ROUTE_STATUS",
1646
+ label: "Route Status",
1647
+ value: "Route Planned"
1648
+ });
1649
+ decodeResult.raw.route_status = header;
1650
+ } else if (header.startsWith("RI")) {
1651
+ decodeResult.raw.route_status = "RI";
1652
+ decodeResult.formatted.items.push({
1653
+ type: "status",
1654
+ code: "ROUTE_STATUS",
1655
+ label: "Route Status",
1656
+ value: "Route Inactive"
1657
+ });
1658
+ } else {
1659
+ decodeResult.remaining.text += header;
1660
+ allKnownFields = false;
1412
1661
  }
1413
1662
  return allKnownFields;
1414
1663
  }
1415
1664
  };
1416
- function parseMessageType(decodeResult, messageType) {
1417
- let decoded = true;
1418
- const parts = messageType.split("#");
1419
- if (parts.length == 1) {
1420
- if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1421
- decoded = processPosition(decodeResult, parts[0].substring(3));
1422
- }
1423
- return decoded;
1424
- } else if (parts.length == 2) {
1425
- if (parts[0].length > 0) {
1426
- decodeResult.remaining.text += parts[0].substring(0, 3);
1427
- decodeResult.raw.flight_number = parts[0].substring(3);
1428
- decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1429
- }
1430
- if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1431
- decoded = processPosition(decodeResult, parts[1].substring(6));
1432
- }
1433
- decodeResult.raw.message_type = messageType;
1434
- return decoded;
1435
- }
1436
- decodeResult.remaining.text += messageType;
1437
- return false;
1665
+ function addArrivalAirport(decodeResult, value) {
1666
+ ResultFormatter.arrivalAirport(decodeResult, value);
1438
1667
  }
1439
- function processPosition(decodeResult, value) {
1440
- const position = CoordinateUtils.decodeStringCoordinates(value);
1441
- if (position) {
1442
- decodeResult.raw.position = position;
1443
- decodeResult.formatted.items.push({
1444
- type: "aircraft_position",
1445
- code: "POS",
1446
- label: "Aircraft Position",
1447
- value: CoordinateUtils.coordinateString(position)
1448
- });
1668
+ function addDepartureAirport(decodeResult, value) {
1669
+ ResultFormatter.departureAirport(decodeResult, value);
1670
+ }
1671
+ function addRunway(decodeResult, value) {
1672
+ if (value.length === 8) {
1673
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1449
1674
  }
1450
- return !!position;
1451
- }
1452
- function addArrivalAirport(decodeResult, value) {
1453
- decodeResult.raw.arrival_icao = value;
1454
- decodeResult.formatted.items.push({
1455
- type: "destination",
1456
- code: "DST",
1457
- label: "Destination",
1458
- value: decodeResult.raw.arrival_icao
1459
- });
1460
- }
1461
- function addDepartureAirport(decodeResult, value) {
1462
- decodeResult.raw.departure_icao = value;
1463
- decodeResult.formatted.items.push({
1464
- type: "origin",
1465
- code: "ORG",
1466
- label: "Origin",
1467
- value: decodeResult.raw.departure_icao
1468
- });
1469
- }
1470
- function addRunway(decodeResult, value) {
1471
- if (value.length === 8) {
1472
- decodeResult.raw.arrival_runway = value.substring(4, 7);
1473
- decodeResult.formatted.items.push({
1474
- type: "runway",
1475
- label: "Arrival Runway",
1476
- value: decodeResult.raw.arrival_runway
1477
- });
1478
- }
1479
- decodeResult.raw.departure_runway = value.substring(0, 3);
1480
- decodeResult.formatted.items.push({
1481
- type: "runway",
1482
- label: "Departure Runway",
1483
- value: decodeResult.raw.departure_runway
1484
- });
1675
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1485
1676
  }
1486
1677
  function addRoute(decodeResult, value) {
1487
1678
  const route = value.split(".");
@@ -1541,6 +1732,286 @@ function addCompanyRoute(decodeResult, value) {
1541
1732
  });
1542
1733
  }
1543
1734
 
1735
+ // lib/utils/h1_helper.ts
1736
+ var H1Helper = class {
1737
+ static decodeH1Message(decodeResult, message) {
1738
+ let allKnownFields = true;
1739
+ const checksum = message.slice(-4);
1740
+ const data = message.slice(0, message.length - 4);
1741
+ const fields = data.split("/");
1742
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1743
+ for (let i = 1; i < fields.length; ++i) {
1744
+ if (fields[i].startsWith("FN")) {
1745
+ decodeResult.raw.flight_number = fields[i].substring(2);
1746
+ } else if (fields[i].startsWith("SN")) {
1747
+ decodeResult.raw.serial_number = fields[i].substring(2);
1748
+ } else if (fields[i].startsWith("DC")) {
1749
+ processDC(decodeResult, fields[i].substring(2).split(","));
1750
+ } else if (fields[i].startsWith("TS")) {
1751
+ const ts = fields[i].substring(2).split(",");
1752
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1753
+ if (Number.isNaN(time)) {
1754
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1755
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1756
+ }
1757
+ decodeResult.raw.message_date = ts[1];
1758
+ decodeResult.raw.message_timestamp = time;
1759
+ } else if (fields[i].startsWith("PS")) {
1760
+ const pos = processPS(decodeResult, fields[i].substring(2).split(","));
1761
+ allKnownFields == allKnownFields && pos;
1762
+ } else if (fields[i].startsWith("DT")) {
1763
+ const data2 = fields[i].substring(2).split(",");
1764
+ const dt = processDT(decodeResult, data2);
1765
+ allKnownFields = allKnownFields && dt;
1766
+ } else if (fields[i].startsWith("ID")) {
1767
+ processIdentification(decodeResult, fields[i].substring(2).split(","));
1768
+ } else if (fields[i].startsWith("LR")) {
1769
+ const data2 = fields[i].substring(2).split(",");
1770
+ const lr = processLR(decodeResult, data2);
1771
+ allKnownFields = allKnownFields && lr;
1772
+ } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1773
+ const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1774
+ allKnownFields = allKnownFields && fp;
1775
+ } else if (fields[i].startsWith("PR")) {
1776
+ allKnownFields = false;
1777
+ decodeResult.remaining.text += "/" + fields[i];
1778
+ } else if (fields[i].startsWith("PS")) {
1779
+ allKnownFields = false;
1780
+ decodeResult.remaining.text += fields[i];
1781
+ } else if (fields[i].startsWith("AF")) {
1782
+ const af = processAirField(decodeResult, fields[i].substring(2).split(","));
1783
+ allKnownFields = allKnownFields && af;
1784
+ } else if (fields[i].startsWith("TD")) {
1785
+ const td = processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
1786
+ allKnownFields = allKnownFields && td;
1787
+ } else if (fields[i].startsWith("FX")) {
1788
+ decodeResult.raw.free_text = fields[i].substring(2);
1789
+ decodeResult.formatted.items.push({
1790
+ type: "text",
1791
+ code: "TEXT",
1792
+ label: "Free Text",
1793
+ value: decodeResult.raw.free_text
1794
+ });
1795
+ } else {
1796
+ decodeResult.remaining.text += "/" + fields[i];
1797
+ allKnownFields = false;
1798
+ }
1799
+ }
1800
+ if (decodeResult.formatted.items.length > 0) {
1801
+ ResultFormatter.checksum(decodeResult, checksum);
1802
+ }
1803
+ return allKnownFields;
1804
+ }
1805
+ };
1806
+ function processAirField(decodeResult, data) {
1807
+ if (data.length === 2) {
1808
+ ResultFormatter.departureAirport(decodeResult, data[0]);
1809
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
1810
+ return true;
1811
+ }
1812
+ decodeResult.remaining.text += "AF/" + data.join(",");
1813
+ return false;
1814
+ }
1815
+ function processTimeOfDeparture(decodeResult, data) {
1816
+ if (data.length === 2) {
1817
+ decodeResult.raw.plannedDepartureTime = data[0];
1818
+ decodeResult.formatted.items.push({
1819
+ type: "ptd",
1820
+ code: "ptd",
1821
+ label: "Planned Departure Time",
1822
+ value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
1823
+ });
1824
+ decodeResult.raw.plannedDepartureTime = data[1];
1825
+ decodeResult.formatted.items.push({
1826
+ type: "etd",
1827
+ code: "etd",
1828
+ label: "Estimated Departure Time",
1829
+ value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
1830
+ });
1831
+ return true;
1832
+ }
1833
+ decodeResult.remaining.text += "/TD" + data.join(",");
1834
+ return false;
1835
+ }
1836
+ function processIdentification(decodeResult, data) {
1837
+ decodeResult.raw.tail = data[0];
1838
+ decodeResult.formatted.items.push({
1839
+ type: "tail",
1840
+ code: "TAIL",
1841
+ label: "Tail",
1842
+ value: decodeResult.raw.tail
1843
+ });
1844
+ if (data.length > 1) {
1845
+ decodeResult.raw.flight_number = data[1];
1846
+ }
1847
+ if (data.length > 2) {
1848
+ decodeResult.raw.mission_number = data[2];
1849
+ }
1850
+ }
1851
+ function processDT(decodeResult, data) {
1852
+ let allKnownFields = true;
1853
+ if (!decodeResult.raw.arrival_icao) {
1854
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
1855
+ } else if (decodeResult.raw.arrival_icao != data[0]) {
1856
+ decodeResult.remaining.text += "/" + data;
1857
+ }
1858
+ if (data.length > 1) {
1859
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
1860
+ }
1861
+ if (data.length > 2) {
1862
+ ResultFormatter.currentFuel(decodeResult, Number(data[2]));
1863
+ }
1864
+ if (data.length > 3) {
1865
+ ResultFormatter.eta(decodeResult, data[3]);
1866
+ }
1867
+ if (data.length > 4) {
1868
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
1869
+ }
1870
+ if (data.length > 5) {
1871
+ allKnownFields = false;
1872
+ decodeResult.remaining.text += "," + data.slice(5).join(",");
1873
+ }
1874
+ return allKnownFields;
1875
+ }
1876
+ function processLR(decodeResult, data) {
1877
+ let allKnownFields = true;
1878
+ if (data.length === 19) {
1879
+ ResultFormatter.unknown(decodeResult, data[1]);
1880
+ ResultFormatter.flightNumber(decodeResult, data[2]);
1881
+ ResultFormatter.departureAirport(decodeResult, data[3]);
1882
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
1883
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
1884
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
1885
+ allKnownFields = false;
1886
+ } else {
1887
+ allKnownFields = false;
1888
+ }
1889
+ return allKnownFields;
1890
+ }
1891
+ function parseMessageType(decodeResult, messageType) {
1892
+ let decoded = true;
1893
+ const parts = messageType.split("#");
1894
+ if (parts.length == 1) {
1895
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1896
+ decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
1897
+ }
1898
+ return decoded;
1899
+ } else if (parts.length == 2) {
1900
+ if (parts[0].length > 0) {
1901
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1902
+ decodeResult.raw.flight_number = parts[0].substring(3);
1903
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1904
+ }
1905
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1906
+ decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
1907
+ }
1908
+ decodeResult.raw.message_type = messageType;
1909
+ return decoded;
1910
+ }
1911
+ decodeResult.remaining.text += messageType;
1912
+ return false;
1913
+ }
1914
+ function processDC(decodeResult, data) {
1915
+ decodeResult.raw.message_date = data[0];
1916
+ if (data.length === 1) {
1917
+ } else if (data.length === 2) {
1918
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
1919
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
1920
+ decodeResult.raw.message_timestamp = time;
1921
+ } else {
1922
+ return false;
1923
+ }
1924
+ return true;
1925
+ }
1926
+ function processPS(decodeResult, data) {
1927
+ let allKnownFields = true;
1928
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1929
+ if (position) {
1930
+ decodeResult.raw.position = position;
1931
+ decodeResult.formatted.items.push({
1932
+ type: "aircraft_position",
1933
+ code: "POS",
1934
+ label: "Aircraft Position",
1935
+ value: CoordinateUtils.coordinateString(position)
1936
+ });
1937
+ } else {
1938
+ allKnownFields = false;
1939
+ }
1940
+ console.log("PS data.length: ", data.length);
1941
+ console.log("PS data: ", data);
1942
+ if (data.length === 9) {
1943
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
1944
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
1945
+ ResultFormatter.temperature(decodeResult, data[6]);
1946
+ ResultFormatter.unknown(decodeResult, data[7]);
1947
+ ResultFormatter.unknown(decodeResult, data[8]);
1948
+ }
1949
+ if (data.length === 14) {
1950
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1951
+ processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
1952
+ ResultFormatter.temperature(decodeResult, data[7]);
1953
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1954
+ ResultFormatter.unknown(decodeResult, data[1]);
1955
+ ResultFormatter.unknown(decodeResult, data[8]);
1956
+ ResultFormatter.unknown(decodeResult, data[9]);
1957
+ ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
1958
+ }
1959
+ allKnownFields = false;
1960
+ return allKnownFields;
1961
+ }
1962
+ function processPosition2(decodeResult, data) {
1963
+ let allKnownFields = true;
1964
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1965
+ if (position) {
1966
+ decodeResult.raw.position = position;
1967
+ decodeResult.formatted.items.push({
1968
+ type: "aircraft_position",
1969
+ code: "POS",
1970
+ label: "Aircraft Position",
1971
+ value: CoordinateUtils.coordinateString(position)
1972
+ });
1973
+ } else {
1974
+ allKnownFields = false;
1975
+ }
1976
+ console.log("data.length: ", data.length);
1977
+ console.log("data: ", data);
1978
+ if (data.length >= 10) {
1979
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1980
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1981
+ ResultFormatter.temperature(decodeResult, data[7]);
1982
+ ResultFormatter.unknown(decodeResult, data[8]);
1983
+ ResultFormatter.unknown(decodeResult, data[9]);
1984
+ }
1985
+ if (data.length >= 14) {
1986
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1987
+ ResultFormatter.unknown(decodeResult, data[11]);
1988
+ ResultFormatter.unknown(decodeResult, data[12]);
1989
+ ResultFormatter.unknown(decodeResult, data[13]);
1990
+ }
1991
+ allKnownFields = false;
1992
+ return allKnownFields;
1993
+ }
1994
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1995
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1996
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1997
+ const timeFormat = date ? "epoch" : "tod";
1998
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1999
+ lastWaypoint.time = lastTime;
2000
+ lastWaypoint.timeFormat = timeFormat;
2001
+ const nextWaypoint = RouteUtils.getWaypoint(next);
2002
+ nextWaypoint.time = nextTime;
2003
+ nextWaypoint.timeFormat = timeFormat;
2004
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
2005
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
2006
+ decodeResult.raw.route = { waypoints };
2007
+ decodeResult.formatted.items.push({
2008
+ type: "aircraft_route",
2009
+ code: "ROUTE",
2010
+ label: "Aircraft Route",
2011
+ value: RouteUtils.routeToString(decodeResult.raw.route)
2012
+ });
2013
+ }
2014
+
1544
2015
  // lib/plugins/Label_H1_FPN.ts
1545
2016
  var Label_H1_FPN = class extends DecoderPlugin {
1546
2017
  name = "label-h1-fpn";
@@ -1555,15 +2026,73 @@ var Label_H1_FPN = class extends DecoderPlugin {
1555
2026
  decodeResult.decoder.name = this.name;
1556
2027
  decodeResult.formatted.description = "Flight Plan";
1557
2028
  decodeResult.message = message;
2029
+ decodeResult.remaining.text = "";
1558
2030
  const msg = message.text.replace(/\n|\r/g, "");
1559
- const checksum = msg.slice(-4);
1560
- const data = msg.slice(0, msg.length - 4).split(":");
1561
- if (data.length > 1) {
1562
- const fulllyDecoded = FlightPlanUtils.processFlightPlan(decodeResult, data);
1563
- addChecksum(decodeResult, checksum);
1564
- decodeResult.decoded = true;
1565
- decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1566
- } else {
2031
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
2032
+ decodeResult.decoded = true;
2033
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2034
+ if (decodeResult.formatted.items.length === 0) {
2035
+ if (options?.debug) {
2036
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2037
+ }
2038
+ decodeResult.remaining.text = message.text;
2039
+ decodeResult.decoded = false;
2040
+ decodeResult.decoder.decodeLevel = "none";
2041
+ }
2042
+ return decodeResult;
2043
+ }
2044
+ };
2045
+
2046
+ // lib/plugins/Label_H1_FTX.ts
2047
+ var Label_H1_FTX = class extends DecoderPlugin {
2048
+ name = "label-h1-ftx";
2049
+ qualifiers() {
2050
+ return {
2051
+ labels: ["H1"],
2052
+ preambles: ["FTX", "- #MDFTX"]
2053
+ };
2054
+ }
2055
+ decode(message, options = {}) {
2056
+ let decodeResult = this.defaultResult();
2057
+ decodeResult.decoder.name = this.name;
2058
+ decodeResult.formatted.description = "Free Text";
2059
+ decodeResult.message = message;
2060
+ decodeResult.remaining.text = "";
2061
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2062
+ decodeResult.decoded = true;
2063
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2064
+ if (decodeResult.formatted.items.length === 0) {
2065
+ if (options?.debug) {
2066
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2067
+ }
2068
+ decodeResult.remaining.text = message.text;
2069
+ decodeResult.decoded = false;
2070
+ decodeResult.decoder.decodeLevel = "none";
2071
+ }
2072
+ return decodeResult;
2073
+ }
2074
+ };
2075
+
2076
+ // lib/plugins/Label_H1_INI.ts
2077
+ var Label_H1_INI = class extends DecoderPlugin {
2078
+ // eslint-disable-line camelcase
2079
+ name = "label-h1-ini";
2080
+ qualifiers() {
2081
+ return {
2082
+ labels: ["H1"],
2083
+ preambles: ["INI", "- #MDINI"]
2084
+ };
2085
+ }
2086
+ decode(message, options = {}) {
2087
+ const decodeResult = this.defaultResult();
2088
+ decodeResult.decoder.name = this.name;
2089
+ decodeResult.formatted.description = "Flight Plan Initial Report";
2090
+ decodeResult.message = message;
2091
+ decodeResult.remaining.text = "";
2092
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2093
+ decodeResult.decoded = true;
2094
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2095
+ if (decodeResult.formatted.items.length === 0) {
1567
2096
  if (options?.debug) {
1568
2097
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1569
2098
  }
@@ -1574,15 +2103,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
1574
2103
  return decodeResult;
1575
2104
  }
1576
2105
  };
1577
- function addChecksum(decodeResult, value) {
1578
- decodeResult.raw.checksum = Number("0x" + value);
1579
- decodeResult.formatted.items.push({
1580
- type: "message_checksum",
1581
- code: "CHECKSUM",
1582
- label: "Message Checksum",
1583
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1584
- });
1585
- }
1586
2106
 
1587
2107
  // lib/plugins/Label_H1_OHMA.ts
1588
2108
  var zlib = __toESM(require("minizlib"));
@@ -1608,13 +2128,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1608
2128
  decompress.flush(zlib.constants.Z_SYNC_FLUSH);
1609
2129
  const result = decompress.read();
1610
2130
  const jsonText = result.toString();
1611
- const json = JSON.parse(jsonText);
1612
2131
  let formattedMsg;
1613
- if (json.message.startsWith("{")) {
1614
- const ohmaMsg = JSON.parse(json.message);
2132
+ let jsonMessage;
2133
+ try {
2134
+ jsonMessage = JSON.parse(jsonText).message;
2135
+ } catch {
2136
+ jsonMessage = jsonText;
2137
+ }
2138
+ try {
2139
+ const ohmaMsg = JSON.parse(jsonMessage);
1615
2140
  formattedMsg = JSON.stringify(ohmaMsg, null, 2);
1616
- } else {
1617
- formattedMsg = json.message;
2141
+ } catch {
2142
+ formattedMsg = jsonMessage;
1618
2143
  }
1619
2144
  decodeResult.decoded = true;
1620
2145
  decodeResult.decoder.decodeLevel = "full";
@@ -1653,225 +2178,20 @@ var Label_H1_POS = class extends DecoderPlugin {
1653
2178
  decodeResult.formatted.description = "Position Report";
1654
2179
  decodeResult.message = message;
1655
2180
  decodeResult.remaining.text = "";
1656
- const checksum = message.text.slice(-4);
1657
- const header = findHeader(message.text.slice(0, -4));
1658
- const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1659
- const parts = message.text.replace(header, "").slice(0, -4).split(",");
1660
- if (parts.length == 1) {
1661
- if (decoded) {
1662
- processChecksum(decodeResult, checksum);
1663
- decodeResult.decoded = true;
1664
- decodeResult.decoder.decodeLevel = "full";
1665
- } else if (decodeResult.remaining.text.length > 0) {
1666
- processChecksum(decodeResult, checksum);
1667
- decodeResult.decoded = true;
1668
- decodeResult.decoder.decodeLevel = "partial";
1669
- } else {
1670
- decodeResult.decoded = false;
1671
- decodeResult.decoder.decodeLevel = "none";
1672
- }
1673
- } else if (parts.length === 10) {
1674
- processAlt(decodeResult, parts[3]);
1675
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1676
- processTemp(decodeResult, parts[7]);
1677
- processUnknown(decodeResult, parts[8]);
1678
- processUnknown(decodeResult, parts[9]);
1679
- processChecksum(decodeResult, checksum);
1680
- decodeResult.decoded = true;
1681
- decodeResult.decoder.decodeLevel = "partial";
1682
- } else if (parts.length === 11) {
1683
- processAlt(decodeResult, parts[3]);
1684
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1685
- processTemp(decodeResult, parts[7]);
1686
- processUnknown(decodeResult, parts[8]);
1687
- processUnknown(decodeResult, parts[9]);
1688
- processChecksum(decodeResult, checksum);
1689
- decodeResult.decoded = true;
1690
- decodeResult.decoder.decodeLevel = "partial";
1691
- } else if (parts.length === 12) {
1692
- const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1693
- processUnknown(decodeResult, parts[3]);
1694
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1695
- processTemp(decodeResult, parts[7]);
1696
- processUnknown(decodeResult, parts[8]);
1697
- processUnknown(decodeResult, parts[9]);
1698
- processUnknown(decodeResult, parts[10]);
1699
- processChecksum(decodeResult, checksum);
1700
- decodeResult.decoded = true;
1701
- decodeResult.decoder.decodeLevel = "partial";
1702
- } else if (parts.length === 14) {
1703
- processAlt(decodeResult, parts[3]);
1704
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1705
- processTemp(decodeResult, parts[7]);
1706
- processUnknown(decodeResult, parts[8]);
1707
- processUnknown(decodeResult, parts[9]);
1708
- processGndspd(decodeResult, parts[10]);
1709
- processUnknown(decodeResult, parts[11]);
1710
- processUnknown(decodeResult, parts[12]);
1711
- processUnknown(decodeResult, parts[13]);
1712
- processChecksum(decodeResult, checksum);
1713
- decodeResult.decoded = true;
1714
- decodeResult.decoder.decodeLevel = "partial";
1715
- } else if (parts.length === 15) {
1716
- decodeResult.raw.flight_number = parts[1];
1717
- let date = void 0;
1718
- if (parts[2].startsWith("/DC")) {
1719
- date = parts[2].substring(3);
1720
- } else {
1721
- processUnknown(decodeResult, parts[2]);
1722
- }
1723
- processUnknown(decodeResult, parts[3]);
1724
- const fields = parts[4].split("/");
1725
- for (let i = 0; i < fields.length; ++i) {
1726
- const field = fields[i];
1727
- if (field.startsWith("PS")) {
1728
- processPosition2(decodeResult, field.substring(2));
1729
- } else {
1730
- if (i === 0) {
1731
- processUnknown(decodeResult, field);
1732
- } else {
1733
- processUnknown(decodeResult, "/" + field);
1734
- }
1735
- }
1736
- }
1737
- processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
1738
- processAlt(decodeResult, parts[6]);
1739
- processTemp(decodeResult, parts[10]);
1740
- processUnknown(decodeResult, parts[11]);
1741
- processUnknown(decodeResult, parts[12]);
1742
- processUnknown(decodeResult, parts[13]);
1743
- processUnknown(decodeResult, parts[14]);
1744
- processChecksum(decodeResult, checksum);
1745
- decodeResult.decoded = true;
1746
- decodeResult.decoder.decodeLevel = "partial";
1747
- } else if (parts.length === 21) {
1748
- processRunway(decodeResult, parts[1]);
1749
- processUnknown(decodeResult, parts.slice(2, 11).join(","));
1750
- processTemp(decodeResult, parts[11]);
1751
- processUnknown(decodeResult, parts.slice(12, 20).join(","));
1752
- FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1753
- processChecksum(decodeResult, checksum);
1754
- decodeResult.decoded = true;
1755
- decodeResult.decoder.decodeLevel = "partial";
1756
- } else if (parts.length === 32) {
1757
- processRunway(decodeResult, parts[1]);
1758
- const time = parts[2];
1759
- processUnknown(decodeResult, parts[3]);
1760
- const past = parts[4];
1761
- processUnknown(decodeResult, parts[5]);
1762
- const eta = parts[6];
1763
- const next = parts[7];
1764
- processUnknown(decodeResult, parts.slice(8, 14).join(","));
1765
- processUnknown(decodeResult, parts[16]);
1766
- processUnknown(decodeResult, parts[17]);
1767
- processUnknown(decodeResult, parts[18]);
1768
- processGndspd(decodeResult, parts[19]);
1769
- processUnknown(decodeResult, parts[20]);
1770
- processUnknown(decodeResult, parts[21]);
1771
- processAlt(decodeResult, parts[22]);
1772
- processUnknown(decodeResult, parts.slice(23, 31).join(","));
1773
- const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1774
- processRoute(decodeResult, past, time, next, eta);
1775
- decodeResult.decoded = true;
1776
- decodeResult.decoder.decodeLevel = "partial";
1777
- } else {
1778
- if (options.debug) {
2181
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2182
+ decodeResult.decoded = true;
2183
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2184
+ if (decodeResult.formatted.items.length === 0) {
2185
+ if (options?.debug) {
1779
2186
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1780
2187
  }
1781
- decodeResult.remaining.text += message.text;
2188
+ decodeResult.remaining.text = message.text;
1782
2189
  decodeResult.decoded = false;
1783
2190
  decodeResult.decoder.decodeLevel = "none";
1784
2191
  }
1785
2192
  return decodeResult;
1786
2193
  }
1787
2194
  };
1788
- function processUnknown(decodeResult, value) {
1789
- decodeResult.remaining.text += "," + value;
1790
- }
1791
- function processPosition2(decodeResult, value) {
1792
- const position = CoordinateUtils.decodeStringCoordinates(value);
1793
- if (position) {
1794
- decodeResult.raw.position = position;
1795
- decodeResult.formatted.items.push({
1796
- type: "aircraft_position",
1797
- code: "POS",
1798
- label: "Aircraft Position",
1799
- value: CoordinateUtils.coordinateString(position)
1800
- });
1801
- }
1802
- }
1803
- function processAlt(decodeResult, value) {
1804
- decodeResult.raw.altitude = Number(value) * 100;
1805
- decodeResult.formatted.items.push({
1806
- type: "altitude",
1807
- code: "ALT",
1808
- label: "Altitude",
1809
- value: `${decodeResult.raw.altitude} feet`
1810
- });
1811
- }
1812
- function processTemp(decodeResult, value) {
1813
- decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1814
- decodeResult.formatted.items.push({
1815
- type: "outside_air_temperature",
1816
- code: "OATEMP",
1817
- label: "Outside Air Temperature (C)",
1818
- value: `${decodeResult.raw.outside_air_temperature}`
1819
- });
1820
- }
1821
- function processRunway(decodeResult, value) {
1822
- decodeResult.raw.arrival_runway = value.replace("RW", "");
1823
- decodeResult.formatted.items.push({
1824
- type: "runway",
1825
- label: "Arrival Runway",
1826
- value: decodeResult.raw.arrival_runway
1827
- });
1828
- }
1829
- function processGndspd(decodeResult, value) {
1830
- decodeResult.raw.groundspeed = Number(value);
1831
- decodeResult.formatted.items.push({
1832
- type: "aircraft_groundspeed",
1833
- code: "GSPD",
1834
- label: "Aircraft Groundspeed",
1835
- value: `${decodeResult.raw.groundspeed}`
1836
- });
1837
- }
1838
- function processRoute(decodeResult, last, time, next, eta, then, date) {
1839
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1840
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1841
- const timeFormat = date ? "epoch" : "tod";
1842
- const lastWaypoint = RouteUtils.getWaypoint(last);
1843
- lastWaypoint.time = lastTime;
1844
- lastWaypoint.timeFormat = timeFormat;
1845
- const nextWaypoint = RouteUtils.getWaypoint(next);
1846
- nextWaypoint.time = nextTime;
1847
- nextWaypoint.timeFormat = timeFormat;
1848
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1849
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1850
- decodeResult.raw.route = { waypoints };
1851
- decodeResult.formatted.items.push({
1852
- type: "aircraft_route",
1853
- code: "ROUTE",
1854
- label: "Aircraft Route",
1855
- value: RouteUtils.routeToString(decodeResult.raw.route)
1856
- });
1857
- }
1858
- function processChecksum(decodeResult, value) {
1859
- decodeResult.raw.checksum = Number("0x" + value);
1860
- decodeResult.formatted.items.push({
1861
- type: "message_checksum",
1862
- code: "CHECKSUM",
1863
- label: "Message Checksum",
1864
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1865
- });
1866
- }
1867
- function findHeader(text) {
1868
- const parts = text.split(",");
1869
- const header = parts[0];
1870
- if (header.indexOf("/TS") === -1) {
1871
- return header;
1872
- }
1873
- return parts[0] + "," + parts[1];
1874
- }
1875
2195
 
1876
2196
  // lib/plugins/Label_H1_WRN.ts
1877
2197
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -3026,6 +3346,7 @@ var MessageDecoder = class {
3026
3346
  this.registerPlugin(new Label_15_FST(this));
3027
3347
  this.registerPlugin(new Label_16_N_Space(this));
3028
3348
  this.registerPlugin(new Label_20_POS(this));
3349
+ this.registerPlugin(new Label_21_POS(this));
3029
3350
  this.registerPlugin(new Label_30_Slash_EA(this));
3030
3351
  this.registerPlugin(new Label_44_ETA(this));
3031
3352
  this.registerPlugin(new Label_44_IN(this));
@@ -3034,6 +3355,9 @@ var MessageDecoder = class {
3034
3355
  this.registerPlugin(new Label_44_POS(this));
3035
3356
  this.registerPlugin(new Label_B6_Forwardslash(this));
3036
3357
  this.registerPlugin(new Label_H1_FPN(this));
3358
+ this.registerPlugin(new Label_H1_FLR(this));
3359
+ this.registerPlugin(new Label_H1_FTX(this));
3360
+ this.registerPlugin(new Label_H1_INI(this));
3037
3361
  this.registerPlugin(new Label_H1_OHMA(this));
3038
3362
  this.registerPlugin(new Label_H1_POS(this));
3039
3363
  this.registerPlugin(new Label_H1_WRN(this));