@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.mjs CHANGED
@@ -171,6 +171,12 @@ var Label_5Z = class extends DecoderPlugin {
171
171
 
172
172
  // lib/utils/coordinate_utils.ts
173
173
  var CoordinateUtils = class {
174
+ /**
175
+ * Decode a string of coordinates into an object with latitude and longitude in millidegrees
176
+ * @param stringCoords - The string of coordinates to decode
177
+ *
178
+ * @returns An object with latitude and longitude properties
179
+ */
174
180
  static decodeStringCoordinates(stringCoords) {
175
181
  var results = {};
176
182
  const firstChar = stringCoords.substring(0, 1);
@@ -188,6 +194,33 @@ var CoordinateUtils = class {
188
194
  }
189
195
  return results;
190
196
  }
197
+ /**
198
+ * Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
199
+ * @param stringCoords - The string of coordinates to decode
200
+ *
201
+ * @returns An object with latitude and longitude properties
202
+ */
203
+ static decodeStringCoordinatesDecimalMinutes(stringCoords) {
204
+ var results = {};
205
+ const firstChar = stringCoords.substring(0, 1);
206
+ let middleChar = stringCoords.substring(6, 7);
207
+ let longitudeChars = stringCoords.substring(7, 13);
208
+ if (middleChar == " ") {
209
+ middleChar = stringCoords.substring(7, 8);
210
+ longitudeChars = stringCoords.substring(8, 14);
211
+ }
212
+ const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
213
+ const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
214
+ const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
215
+ const lonMin = Number(longitudeChars) % 1e3 / 10;
216
+ if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
217
+ results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
218
+ results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
219
+ } else {
220
+ return;
221
+ }
222
+ return results;
223
+ }
191
224
  static coordinateString(coords) {
192
225
  const latDir = coords.latitude > 0 ? "N" : "S";
193
226
  const lonDir = coords.longitude > 0 ? "E" : "W";
@@ -558,6 +591,96 @@ var Label_20_POS = class extends DecoderPlugin {
558
591
  }
559
592
  };
560
593
 
594
+ // lib/plugins/Label_21_POS.ts
595
+ var Label_21_POS = class extends DecoderPlugin {
596
+ name = "label-21-pos";
597
+ qualifiers() {
598
+ return {
599
+ labels: ["21"],
600
+ preambles: ["POS"]
601
+ };
602
+ }
603
+ decode(message, options = {}) {
604
+ const decodeResult = this.defaultResult();
605
+ decodeResult.decoder.name = this.name;
606
+ decodeResult.formatted.description = "Position Report";
607
+ decodeResult.message = message;
608
+ decodeResult.raw.preamble = message.text.substring(0, 3);
609
+ const content = message.text.substring(3);
610
+ console.log("Content: " + content);
611
+ const fields = content.split(",");
612
+ console.log("Field Count: " + fields.length);
613
+ if (fields.length == 9) {
614
+ processPosition(decodeResult, fields[0].trim());
615
+ processAlt(decodeResult, fields[3]);
616
+ processTemp(decodeResult, fields[6]);
617
+ processArrvApt(decodeResult, fields[8]);
618
+ decodeResult.raw.remaining = [
619
+ fields[1],
620
+ fields[2],
621
+ fields[4],
622
+ fields[5],
623
+ fields[7]
624
+ ].join(",");
625
+ decodeResult.decoded = true;
626
+ decodeResult.decoder.decodeLevel = "partial";
627
+ } else {
628
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
629
+ decodeResult.decoded = false;
630
+ decodeResult.decoder.decodeLevel = "none";
631
+ }
632
+ return decodeResult;
633
+ }
634
+ };
635
+ function processPosition(decodeResult, value) {
636
+ if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
637
+ return false;
638
+ }
639
+ const latDir = value[0] === "N" ? 1 : -1;
640
+ const lonDir = value[8] === "E" ? 1 : -1;
641
+ const position = {
642
+ latitude: latDir * Number(value.substring(1, 7)),
643
+ longitude: lonDir * Number(value.substring(9, 15))
644
+ };
645
+ if (position) {
646
+ decodeResult.raw.position = position;
647
+ decodeResult.formatted.items.push({
648
+ type: "aircraft_position",
649
+ code: "POS",
650
+ label: "Aircraft Position",
651
+ value: CoordinateUtils.coordinateString(position)
652
+ });
653
+ }
654
+ return !!position;
655
+ }
656
+ function processAlt(decodeResult, value) {
657
+ decodeResult.raw.altitude = Number(value);
658
+ decodeResult.formatted.items.push({
659
+ type: "altitude",
660
+ code: "ALT",
661
+ label: "Altitude",
662
+ value: `${decodeResult.raw.altitude} feet`
663
+ });
664
+ }
665
+ function processTemp(decodeResult, value) {
666
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
667
+ decodeResult.formatted.items.push({
668
+ type: "outside_air_temperature",
669
+ code: "OATEMP",
670
+ label: "Outside Air Temperature (C)",
671
+ value: `${decodeResult.raw.outside_air_temperature}`
672
+ });
673
+ }
674
+ function processArrvApt(decodeResult, value) {
675
+ decodeResult.raw.arrival_icao = value;
676
+ decodeResult.formatted.items.push({
677
+ type: "destination",
678
+ code: "DST",
679
+ label: "Destination",
680
+ value: decodeResult.raw.arrival_icao
681
+ });
682
+ }
683
+
561
684
  // lib/plugins/Label_30_Slash_EA.ts
562
685
  var Label_30_Slash_EA = class extends DecoderPlugin {
563
686
  name = "label-30-slash-ea";
@@ -855,7 +978,7 @@ var Label_44_POS = class extends DecoderPlugin {
855
978
  console.log(`Label 44 Position Report: groups`);
856
979
  console.log(results.groups);
857
980
  }
858
- decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
981
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
859
982
  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);
860
983
  decodeResult.raw.departure_icao = results.groups.departure_icao;
861
984
  decodeResult.raw.arrival_icao = results.groups.arrival_icao;
@@ -870,9 +993,9 @@ var Label_44_POS = class extends DecoderPlugin {
870
993
  }
871
994
  if (decodeResult.raw.position) {
872
995
  decodeResult.formatted.items.push({
873
- type: "position",
996
+ type: "aircraft_position",
874
997
  code: "POS",
875
- label: "Position",
998
+ label: "Aircraft Position",
876
999
  value: CoordinateUtils.coordinateString(decodeResult.raw.position)
877
1000
  });
878
1001
  }
@@ -1180,6 +1303,168 @@ var Label_ColonComma = class extends DecoderPlugin {
1180
1303
  }
1181
1304
  };
1182
1305
 
1306
+ // lib/plugins/Label_H1_FLR.ts
1307
+ var Label_H1_FLR = class extends DecoderPlugin {
1308
+ name = "label-h1-flr";
1309
+ qualifiers() {
1310
+ return {
1311
+ labels: ["H1"],
1312
+ preambles: ["FLR", "#CFBFLR"]
1313
+ };
1314
+ }
1315
+ decode(message, options = {}) {
1316
+ let decodeResult = this.defaultResult();
1317
+ decodeResult.decoder.name = this.name;
1318
+ decodeResult.formatted.description = "Fault Log Report";
1319
+ decodeResult.message = message;
1320
+ const parts = message.text.split("/FR");
1321
+ if (parts.length > 1) {
1322
+ decodeResult.remaining.text = "";
1323
+ const fields = parts[0].split("/");
1324
+ for (let i = 1; i < fields.length; i++) {
1325
+ const field = fields[i];
1326
+ if (field.startsWith("PN")) {
1327
+ processUnknown(decodeResult, "/" + field);
1328
+ } else {
1329
+ processUnknown(decodeResult, "/" + field);
1330
+ }
1331
+ }
1332
+ const data = parts[1].substring(0, 20);
1333
+ const msg = parts[1].substring(20);
1334
+ const datetime = data.substring(0, 12);
1335
+ const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
1336
+ processUnknown(decodeResult, data.substring(12));
1337
+ decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
1338
+ decodeResult.raw.fault_message = msg;
1339
+ decodeResult.formatted.items.push({
1340
+ type: "fault",
1341
+ code: "FR",
1342
+ label: "Fault Report",
1343
+ value: decodeResult.raw.fault_message
1344
+ });
1345
+ decodeResult.decoded = true;
1346
+ decodeResult.decoder.decodeLevel = "partial";
1347
+ } else {
1348
+ if (options.debug) {
1349
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
1350
+ }
1351
+ decodeResult.remaining.text = message.text;
1352
+ decodeResult.decoded = false;
1353
+ decodeResult.decoder.decodeLevel = "none";
1354
+ }
1355
+ return decodeResult;
1356
+ }
1357
+ };
1358
+ function processUnknown(decodeResult, value) {
1359
+ decodeResult.remaining.text += value;
1360
+ }
1361
+
1362
+ // lib/utils/result_formatter.ts
1363
+ var ResultFormatter = class {
1364
+ static altitude(decodeResult, value) {
1365
+ decodeResult.raw.altitude = value;
1366
+ decodeResult.formatted.items.push({
1367
+ type: "altitude",
1368
+ code: "ALT",
1369
+ label: "Altitude",
1370
+ value: `${decodeResult.raw.altitude} feet`
1371
+ });
1372
+ }
1373
+ static flightNumber(decodeResult, value) {
1374
+ decodeResult.raw.flight_number = value;
1375
+ }
1376
+ static departureAirport(decodeResult, value) {
1377
+ decodeResult.raw.departure_icao = value;
1378
+ decodeResult.formatted.items.push({
1379
+ type: "origin",
1380
+ code: "ORG",
1381
+ label: "Origin",
1382
+ value: decodeResult.raw.departure_icao
1383
+ });
1384
+ }
1385
+ static departureRunway(decodeResult, value) {
1386
+ decodeResult.raw.departure_runway = value;
1387
+ decodeResult.formatted.items.push({
1388
+ type: "runway",
1389
+ code: "DEPRWY",
1390
+ label: "Departure Runway",
1391
+ value: decodeResult.raw.departure_runway
1392
+ });
1393
+ }
1394
+ static arrivalAirport(decodeResult, value) {
1395
+ decodeResult.raw.arrival_icao = value;
1396
+ decodeResult.formatted.items.push({
1397
+ type: "destination",
1398
+ code: "DST",
1399
+ label: "Destination",
1400
+ value: decodeResult.raw.arrival_icao
1401
+ });
1402
+ }
1403
+ static eta(decodeResult, value) {
1404
+ decodeResult.formatted.items.push({
1405
+ type: "eta",
1406
+ code: "ETA",
1407
+ label: "Estimated Time of Arrival",
1408
+ value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
1409
+ });
1410
+ }
1411
+ static arrivalRunway(decodeResult, value) {
1412
+ decodeResult.raw.arrival_runway = value;
1413
+ decodeResult.formatted.items.push({
1414
+ type: "runway",
1415
+ label: "Arrival Runway",
1416
+ value: decodeResult.raw.arrival_runway
1417
+ });
1418
+ }
1419
+ static currentFuel(decodeResult, value) {
1420
+ decodeResult.raw.fuel_on_board = value;
1421
+ decodeResult.formatted.items.push({
1422
+ type: "fuel_on_board",
1423
+ code: "FOB",
1424
+ label: "Fuel On Board",
1425
+ value: decodeResult.raw.fuel_on_board.toString()
1426
+ });
1427
+ }
1428
+ static remainingFuel(decodeResult, value) {
1429
+ decodeResult.raw.fuel_remaining = value;
1430
+ decodeResult.formatted.items.push({
1431
+ type: "fuel_remaining",
1432
+ label: "Fuel Remaining",
1433
+ value: decodeResult.raw.fuel_remaining.toString()
1434
+ });
1435
+ }
1436
+ static checksum(decodeResult, value) {
1437
+ decodeResult.raw.checksum = Number("0x" + value);
1438
+ decodeResult.formatted.items.push({
1439
+ type: "message_checksum",
1440
+ code: "CHECKSUM",
1441
+ label: "Message Checksum",
1442
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1443
+ });
1444
+ }
1445
+ static groundspeed(decodeResult, value) {
1446
+ decodeResult.raw.groundspeed = value;
1447
+ decodeResult.formatted.items.push({
1448
+ type: "aircraft_groundspeed",
1449
+ code: "GSPD",
1450
+ label: "Aircraft Groundspeed",
1451
+ value: `${decodeResult.raw.groundspeed}`
1452
+ });
1453
+ }
1454
+ static temperature(decodeResult, value) {
1455
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1456
+ decodeResult.formatted.items.push({
1457
+ type: "outside_air_temperature",
1458
+ code: "OATEMP",
1459
+ label: "Outside Air Temperature (C)",
1460
+ value: `${decodeResult.raw.outside_air_temperature}`
1461
+ });
1462
+ }
1463
+ static unknown(decodeResult, value) {
1464
+ decodeResult.remaining.text += "," + value;
1465
+ }
1466
+ };
1467
+
1183
1468
  // lib/utils/route_utils.ts
1184
1469
  var RouteUtils = class _RouteUtils {
1185
1470
  static routeToString(route) {
@@ -1220,13 +1505,13 @@ var RouteUtils = class _RouteUtils {
1220
1505
  }
1221
1506
  const waypoint = leg.split(",");
1222
1507
  if (waypoint.length == 2) {
1223
- const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1508
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
1224
1509
  if (position) {
1225
1510
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1226
1511
  }
1227
1512
  }
1228
1513
  if (leg.length == 13 || leg.length == 14) {
1229
- const position = CoordinateUtils.decodeStringCoordinates(leg);
1514
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
1230
1515
  const name = waypoint.length == 2 ? waypoint[0] : "";
1231
1516
  if (position) {
1232
1517
  return { name, latitude: position.latitude, longitude: position.longitude };
@@ -1305,146 +1590,52 @@ var FlightPlanUtils = class _FlightPlanUtils {
1305
1590
  }
1306
1591
  static parseHeader(decodeResult, header) {
1307
1592
  let allKnownFields = true;
1308
- const fields = header.split("/");
1309
- allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1310
- for (let i = 1; i < fields.length; ++i) {
1311
- if (fields[i].startsWith("FN")) {
1312
- decodeResult.raw.flight_number = fields[i].substring(2);
1313
- } else if (fields[i].startsWith("SN")) {
1314
- decodeResult.raw.serial_number = fields[i].substring(2);
1315
- } else if (fields[i].startsWith("TS")) {
1316
- const ts = fields[i].substring(2).split(",");
1317
- let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1318
- if (Number.isNaN(time)) {
1319
- const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1320
- time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1321
- }
1322
- decodeResult.raw.message_timestamp = time;
1323
- } else if (fields[i].startsWith("PS")) {
1324
- const pos = fields[i].substring(2);
1325
- allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1326
- } else if (fields[i].startsWith("DT")) {
1327
- const icao = fields[i].substring(2);
1328
- decodeResult.raw.arrival_icao = icao;
1329
- decodeResult.formatted.items.push({
1330
- type: "destination",
1331
- code: "DST",
1332
- label: "Destination",
1333
- value: decodeResult.raw.arrival_icao
1334
- });
1335
- } else if (fields[i].startsWith("ID")) {
1336
- const tail = fields[i].substring(2);
1337
- decodeResult.raw.tail = tail;
1338
- decodeResult.formatted.items.push({
1339
- type: "tail",
1340
- label: "Tail",
1341
- value: decodeResult.raw.tail
1342
- });
1343
- } else if (fields[i].startsWith("RF")) {
1344
- decodeResult.formatted.items.push({
1345
- type: "status",
1346
- code: "ROUTE_STATUS",
1347
- label: "Route Status",
1348
- value: "Route Filed"
1349
- });
1350
- decodeResult.raw.route_status = "RF";
1351
- if (fields[i].length > 2) {
1352
- addRoute(decodeResult, fields[i].substring(2));
1353
- }
1354
- } else if (fields[i] == "RP") {
1355
- decodeResult.raw.route_status = "RP";
1356
- decodeResult.formatted.items.push({
1357
- type: "status",
1358
- code: "ROUTE_STATUS",
1359
- label: "Route Status",
1360
- value: "Route Planned"
1361
- });
1362
- decodeResult.raw.route_status = fields[i];
1363
- } else if (fields[i] == "RI") {
1364
- decodeResult.raw.route_status = "RI";
1365
- decodeResult.formatted.items.push({
1366
- type: "status",
1367
- code: "ROUTE_STATUS",
1368
- label: "Route Status",
1369
- value: "Route Inactive"
1370
- });
1371
- } else {
1372
- decodeResult.remaining.text += "/" + fields[i];
1373
- allKnownFields = false;
1593
+ if (header.startsWith("RF")) {
1594
+ decodeResult.formatted.items.push({
1595
+ type: "status",
1596
+ code: "ROUTE_STATUS",
1597
+ label: "Route Status",
1598
+ value: "Route Filed"
1599
+ });
1600
+ decodeResult.raw.route_status = "RF";
1601
+ if (header.length > 2) {
1602
+ addRoute(decodeResult, header.substring(2));
1374
1603
  }
1604
+ } else if (header.startsWith("RP")) {
1605
+ decodeResult.raw.route_status = "RP";
1606
+ decodeResult.formatted.items.push({
1607
+ type: "status",
1608
+ code: "ROUTE_STATUS",
1609
+ label: "Route Status",
1610
+ value: "Route Planned"
1611
+ });
1612
+ decodeResult.raw.route_status = header;
1613
+ } else if (header.startsWith("RI")) {
1614
+ decodeResult.raw.route_status = "RI";
1615
+ decodeResult.formatted.items.push({
1616
+ type: "status",
1617
+ code: "ROUTE_STATUS",
1618
+ label: "Route Status",
1619
+ value: "Route Inactive"
1620
+ });
1621
+ } else {
1622
+ decodeResult.remaining.text += header;
1623
+ allKnownFields = false;
1375
1624
  }
1376
1625
  return allKnownFields;
1377
1626
  }
1378
1627
  };
1379
- function parseMessageType(decodeResult, messageType) {
1380
- let decoded = true;
1381
- const parts = messageType.split("#");
1382
- if (parts.length == 1) {
1383
- if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1384
- decoded = processPosition(decodeResult, parts[0].substring(3));
1385
- }
1386
- return decoded;
1387
- } else if (parts.length == 2) {
1388
- if (parts[0].length > 0) {
1389
- decodeResult.remaining.text += parts[0].substring(0, 3);
1390
- decodeResult.raw.flight_number = parts[0].substring(3);
1391
- decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1392
- }
1393
- if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1394
- decoded = processPosition(decodeResult, parts[1].substring(6));
1395
- }
1396
- decodeResult.raw.message_type = messageType;
1397
- return decoded;
1398
- }
1399
- decodeResult.remaining.text += messageType;
1400
- return false;
1628
+ function addArrivalAirport(decodeResult, value) {
1629
+ ResultFormatter.arrivalAirport(decodeResult, value);
1401
1630
  }
1402
- function processPosition(decodeResult, value) {
1403
- const position = CoordinateUtils.decodeStringCoordinates(value);
1404
- if (position) {
1405
- decodeResult.raw.position = position;
1406
- decodeResult.formatted.items.push({
1407
- type: "aircraft_position",
1408
- code: "POS",
1409
- label: "Aircraft Position",
1410
- value: CoordinateUtils.coordinateString(position)
1411
- });
1631
+ function addDepartureAirport(decodeResult, value) {
1632
+ ResultFormatter.departureAirport(decodeResult, value);
1633
+ }
1634
+ function addRunway(decodeResult, value) {
1635
+ if (value.length === 8) {
1636
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1412
1637
  }
1413
- return !!position;
1414
- }
1415
- function addArrivalAirport(decodeResult, value) {
1416
- decodeResult.raw.arrival_icao = value;
1417
- decodeResult.formatted.items.push({
1418
- type: "destination",
1419
- code: "DST",
1420
- label: "Destination",
1421
- value: decodeResult.raw.arrival_icao
1422
- });
1423
- }
1424
- function addDepartureAirport(decodeResult, value) {
1425
- decodeResult.raw.departure_icao = value;
1426
- decodeResult.formatted.items.push({
1427
- type: "origin",
1428
- code: "ORG",
1429
- label: "Origin",
1430
- value: decodeResult.raw.departure_icao
1431
- });
1432
- }
1433
- function addRunway(decodeResult, value) {
1434
- if (value.length === 8) {
1435
- decodeResult.raw.arrival_runway = value.substring(4, 7);
1436
- decodeResult.formatted.items.push({
1437
- type: "runway",
1438
- label: "Arrival Runway",
1439
- value: decodeResult.raw.arrival_runway
1440
- });
1441
- }
1442
- decodeResult.raw.departure_runway = value.substring(0, 3);
1443
- decodeResult.formatted.items.push({
1444
- type: "runway",
1445
- label: "Departure Runway",
1446
- value: decodeResult.raw.departure_runway
1447
- });
1638
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1448
1639
  }
1449
1640
  function addRoute(decodeResult, value) {
1450
1641
  const route = value.split(".");
@@ -1504,6 +1695,286 @@ function addCompanyRoute(decodeResult, value) {
1504
1695
  });
1505
1696
  }
1506
1697
 
1698
+ // lib/utils/h1_helper.ts
1699
+ var H1Helper = class {
1700
+ static decodeH1Message(decodeResult, message) {
1701
+ let allKnownFields = true;
1702
+ const checksum = message.slice(-4);
1703
+ const data = message.slice(0, message.length - 4);
1704
+ const fields = data.split("/");
1705
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1706
+ for (let i = 1; i < fields.length; ++i) {
1707
+ if (fields[i].startsWith("FN")) {
1708
+ decodeResult.raw.flight_number = fields[i].substring(2);
1709
+ } else if (fields[i].startsWith("SN")) {
1710
+ decodeResult.raw.serial_number = fields[i].substring(2);
1711
+ } else if (fields[i].startsWith("DC")) {
1712
+ processDC(decodeResult, fields[i].substring(2).split(","));
1713
+ } else if (fields[i].startsWith("TS")) {
1714
+ const ts = fields[i].substring(2).split(",");
1715
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1716
+ if (Number.isNaN(time)) {
1717
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1718
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1719
+ }
1720
+ decodeResult.raw.message_date = ts[1];
1721
+ decodeResult.raw.message_timestamp = time;
1722
+ } else if (fields[i].startsWith("PS")) {
1723
+ const pos = processPS(decodeResult, fields[i].substring(2).split(","));
1724
+ allKnownFields == allKnownFields && pos;
1725
+ } else if (fields[i].startsWith("DT")) {
1726
+ const data2 = fields[i].substring(2).split(",");
1727
+ const dt = processDT(decodeResult, data2);
1728
+ allKnownFields = allKnownFields && dt;
1729
+ } else if (fields[i].startsWith("ID")) {
1730
+ processIdentification(decodeResult, fields[i].substring(2).split(","));
1731
+ } else if (fields[i].startsWith("LR")) {
1732
+ const data2 = fields[i].substring(2).split(",");
1733
+ const lr = processLR(decodeResult, data2);
1734
+ allKnownFields = allKnownFields && lr;
1735
+ } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1736
+ const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1737
+ allKnownFields = allKnownFields && fp;
1738
+ } else if (fields[i].startsWith("PR")) {
1739
+ allKnownFields = false;
1740
+ decodeResult.remaining.text += "/" + fields[i];
1741
+ } else if (fields[i].startsWith("PS")) {
1742
+ allKnownFields = false;
1743
+ decodeResult.remaining.text += fields[i];
1744
+ } else if (fields[i].startsWith("AF")) {
1745
+ const af = processAirField(decodeResult, fields[i].substring(2).split(","));
1746
+ allKnownFields = allKnownFields && af;
1747
+ } else if (fields[i].startsWith("TD")) {
1748
+ const td = processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
1749
+ allKnownFields = allKnownFields && td;
1750
+ } else if (fields[i].startsWith("FX")) {
1751
+ decodeResult.raw.free_text = fields[i].substring(2);
1752
+ decodeResult.formatted.items.push({
1753
+ type: "text",
1754
+ code: "TEXT",
1755
+ label: "Free Text",
1756
+ value: decodeResult.raw.free_text
1757
+ });
1758
+ } else {
1759
+ decodeResult.remaining.text += "/" + fields[i];
1760
+ allKnownFields = false;
1761
+ }
1762
+ }
1763
+ if (decodeResult.formatted.items.length > 0) {
1764
+ ResultFormatter.checksum(decodeResult, checksum);
1765
+ }
1766
+ return allKnownFields;
1767
+ }
1768
+ };
1769
+ function processAirField(decodeResult, data) {
1770
+ if (data.length === 2) {
1771
+ ResultFormatter.departureAirport(decodeResult, data[0]);
1772
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
1773
+ return true;
1774
+ }
1775
+ decodeResult.remaining.text += "AF/" + data.join(",");
1776
+ return false;
1777
+ }
1778
+ function processTimeOfDeparture(decodeResult, data) {
1779
+ if (data.length === 2) {
1780
+ decodeResult.raw.plannedDepartureTime = data[0];
1781
+ decodeResult.formatted.items.push({
1782
+ type: "ptd",
1783
+ code: "ptd",
1784
+ label: "Planned Departure Time",
1785
+ value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
1786
+ });
1787
+ decodeResult.raw.plannedDepartureTime = data[1];
1788
+ decodeResult.formatted.items.push({
1789
+ type: "etd",
1790
+ code: "etd",
1791
+ label: "Estimated Departure Time",
1792
+ value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
1793
+ });
1794
+ return true;
1795
+ }
1796
+ decodeResult.remaining.text += "/TD" + data.join(",");
1797
+ return false;
1798
+ }
1799
+ function processIdentification(decodeResult, data) {
1800
+ decodeResult.raw.tail = data[0];
1801
+ decodeResult.formatted.items.push({
1802
+ type: "tail",
1803
+ code: "TAIL",
1804
+ label: "Tail",
1805
+ value: decodeResult.raw.tail
1806
+ });
1807
+ if (data.length > 1) {
1808
+ decodeResult.raw.flight_number = data[1];
1809
+ }
1810
+ if (data.length > 2) {
1811
+ decodeResult.raw.mission_number = data[2];
1812
+ }
1813
+ }
1814
+ function processDT(decodeResult, data) {
1815
+ let allKnownFields = true;
1816
+ if (!decodeResult.raw.arrival_icao) {
1817
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
1818
+ } else if (decodeResult.raw.arrival_icao != data[0]) {
1819
+ decodeResult.remaining.text += "/" + data;
1820
+ }
1821
+ if (data.length > 1) {
1822
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
1823
+ }
1824
+ if (data.length > 2) {
1825
+ ResultFormatter.currentFuel(decodeResult, Number(data[2]));
1826
+ }
1827
+ if (data.length > 3) {
1828
+ ResultFormatter.eta(decodeResult, data[3]);
1829
+ }
1830
+ if (data.length > 4) {
1831
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
1832
+ }
1833
+ if (data.length > 5) {
1834
+ allKnownFields = false;
1835
+ decodeResult.remaining.text += "," + data.slice(5).join(",");
1836
+ }
1837
+ return allKnownFields;
1838
+ }
1839
+ function processLR(decodeResult, data) {
1840
+ let allKnownFields = true;
1841
+ if (data.length === 19) {
1842
+ ResultFormatter.unknown(decodeResult, data[1]);
1843
+ ResultFormatter.flightNumber(decodeResult, data[2]);
1844
+ ResultFormatter.departureAirport(decodeResult, data[3]);
1845
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
1846
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
1847
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
1848
+ allKnownFields = false;
1849
+ } else {
1850
+ allKnownFields = false;
1851
+ }
1852
+ return allKnownFields;
1853
+ }
1854
+ function parseMessageType(decodeResult, messageType) {
1855
+ let decoded = true;
1856
+ const parts = messageType.split("#");
1857
+ if (parts.length == 1) {
1858
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1859
+ decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
1860
+ }
1861
+ return decoded;
1862
+ } else if (parts.length == 2) {
1863
+ if (parts[0].length > 0) {
1864
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1865
+ decodeResult.raw.flight_number = parts[0].substring(3);
1866
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1867
+ }
1868
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1869
+ decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
1870
+ }
1871
+ decodeResult.raw.message_type = messageType;
1872
+ return decoded;
1873
+ }
1874
+ decodeResult.remaining.text += messageType;
1875
+ return false;
1876
+ }
1877
+ function processDC(decodeResult, data) {
1878
+ decodeResult.raw.message_date = data[0];
1879
+ if (data.length === 1) {
1880
+ } else if (data.length === 2) {
1881
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
1882
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
1883
+ decodeResult.raw.message_timestamp = time;
1884
+ } else {
1885
+ return false;
1886
+ }
1887
+ return true;
1888
+ }
1889
+ function processPS(decodeResult, data) {
1890
+ let allKnownFields = true;
1891
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1892
+ if (position) {
1893
+ decodeResult.raw.position = position;
1894
+ decodeResult.formatted.items.push({
1895
+ type: "aircraft_position",
1896
+ code: "POS",
1897
+ label: "Aircraft Position",
1898
+ value: CoordinateUtils.coordinateString(position)
1899
+ });
1900
+ } else {
1901
+ allKnownFields = false;
1902
+ }
1903
+ console.log("PS data.length: ", data.length);
1904
+ console.log("PS data: ", data);
1905
+ if (data.length === 9) {
1906
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
1907
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
1908
+ ResultFormatter.temperature(decodeResult, data[6]);
1909
+ ResultFormatter.unknown(decodeResult, data[7]);
1910
+ ResultFormatter.unknown(decodeResult, data[8]);
1911
+ }
1912
+ if (data.length === 14) {
1913
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1914
+ processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
1915
+ ResultFormatter.temperature(decodeResult, data[7]);
1916
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1917
+ ResultFormatter.unknown(decodeResult, data[1]);
1918
+ ResultFormatter.unknown(decodeResult, data[8]);
1919
+ ResultFormatter.unknown(decodeResult, data[9]);
1920
+ ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
1921
+ }
1922
+ allKnownFields = false;
1923
+ return allKnownFields;
1924
+ }
1925
+ function processPosition2(decodeResult, data) {
1926
+ let allKnownFields = true;
1927
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1928
+ if (position) {
1929
+ decodeResult.raw.position = position;
1930
+ decodeResult.formatted.items.push({
1931
+ type: "aircraft_position",
1932
+ code: "POS",
1933
+ label: "Aircraft Position",
1934
+ value: CoordinateUtils.coordinateString(position)
1935
+ });
1936
+ } else {
1937
+ allKnownFields = false;
1938
+ }
1939
+ console.log("data.length: ", data.length);
1940
+ console.log("data: ", data);
1941
+ if (data.length >= 10) {
1942
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1943
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1944
+ ResultFormatter.temperature(decodeResult, data[7]);
1945
+ ResultFormatter.unknown(decodeResult, data[8]);
1946
+ ResultFormatter.unknown(decodeResult, data[9]);
1947
+ }
1948
+ if (data.length >= 14) {
1949
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1950
+ ResultFormatter.unknown(decodeResult, data[11]);
1951
+ ResultFormatter.unknown(decodeResult, data[12]);
1952
+ ResultFormatter.unknown(decodeResult, data[13]);
1953
+ }
1954
+ allKnownFields = false;
1955
+ return allKnownFields;
1956
+ }
1957
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1958
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1959
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1960
+ const timeFormat = date ? "epoch" : "tod";
1961
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1962
+ lastWaypoint.time = lastTime;
1963
+ lastWaypoint.timeFormat = timeFormat;
1964
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1965
+ nextWaypoint.time = nextTime;
1966
+ nextWaypoint.timeFormat = timeFormat;
1967
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1968
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1969
+ decodeResult.raw.route = { waypoints };
1970
+ decodeResult.formatted.items.push({
1971
+ type: "aircraft_route",
1972
+ code: "ROUTE",
1973
+ label: "Aircraft Route",
1974
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1975
+ });
1976
+ }
1977
+
1507
1978
  // lib/plugins/Label_H1_FPN.ts
1508
1979
  var Label_H1_FPN = class extends DecoderPlugin {
1509
1980
  name = "label-h1-fpn";
@@ -1518,15 +1989,73 @@ var Label_H1_FPN = class extends DecoderPlugin {
1518
1989
  decodeResult.decoder.name = this.name;
1519
1990
  decodeResult.formatted.description = "Flight Plan";
1520
1991
  decodeResult.message = message;
1992
+ decodeResult.remaining.text = "";
1521
1993
  const msg = message.text.replace(/\n|\r/g, "");
1522
- const checksum = msg.slice(-4);
1523
- const data = msg.slice(0, msg.length - 4).split(":");
1524
- if (data.length > 1) {
1525
- const fulllyDecoded = FlightPlanUtils.processFlightPlan(decodeResult, data);
1526
- addChecksum(decodeResult, checksum);
1527
- decodeResult.decoded = true;
1528
- decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1529
- } else {
1994
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
1995
+ decodeResult.decoded = true;
1996
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1997
+ if (decodeResult.formatted.items.length === 0) {
1998
+ if (options?.debug) {
1999
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2000
+ }
2001
+ decodeResult.remaining.text = message.text;
2002
+ decodeResult.decoded = false;
2003
+ decodeResult.decoder.decodeLevel = "none";
2004
+ }
2005
+ return decodeResult;
2006
+ }
2007
+ };
2008
+
2009
+ // lib/plugins/Label_H1_FTX.ts
2010
+ var Label_H1_FTX = class extends DecoderPlugin {
2011
+ name = "label-h1-ftx";
2012
+ qualifiers() {
2013
+ return {
2014
+ labels: ["H1"],
2015
+ preambles: ["FTX", "- #MDFTX"]
2016
+ };
2017
+ }
2018
+ decode(message, options = {}) {
2019
+ let decodeResult = this.defaultResult();
2020
+ decodeResult.decoder.name = this.name;
2021
+ decodeResult.formatted.description = "Free Text";
2022
+ decodeResult.message = message;
2023
+ decodeResult.remaining.text = "";
2024
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2025
+ decodeResult.decoded = true;
2026
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2027
+ if (decodeResult.formatted.items.length === 0) {
2028
+ if (options?.debug) {
2029
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2030
+ }
2031
+ decodeResult.remaining.text = message.text;
2032
+ decodeResult.decoded = false;
2033
+ decodeResult.decoder.decodeLevel = "none";
2034
+ }
2035
+ return decodeResult;
2036
+ }
2037
+ };
2038
+
2039
+ // lib/plugins/Label_H1_INI.ts
2040
+ var Label_H1_INI = class extends DecoderPlugin {
2041
+ // eslint-disable-line camelcase
2042
+ name = "label-h1-ini";
2043
+ qualifiers() {
2044
+ return {
2045
+ labels: ["H1"],
2046
+ preambles: ["INI", "- #MDINI"]
2047
+ };
2048
+ }
2049
+ decode(message, options = {}) {
2050
+ const decodeResult = this.defaultResult();
2051
+ decodeResult.decoder.name = this.name;
2052
+ decodeResult.formatted.description = "Flight Plan Initial Report";
2053
+ decodeResult.message = message;
2054
+ decodeResult.remaining.text = "";
2055
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2056
+ decodeResult.decoded = true;
2057
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2058
+ if (decodeResult.formatted.items.length === 0) {
1530
2059
  if (options?.debug) {
1531
2060
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1532
2061
  }
@@ -1537,15 +2066,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
1537
2066
  return decodeResult;
1538
2067
  }
1539
2068
  };
1540
- function addChecksum(decodeResult, value) {
1541
- decodeResult.raw.checksum = Number("0x" + value);
1542
- decodeResult.formatted.items.push({
1543
- type: "message_checksum",
1544
- code: "CHECKSUM",
1545
- label: "Message Checksum",
1546
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1547
- });
1548
- }
1549
2069
 
1550
2070
  // lib/plugins/Label_H1_OHMA.ts
1551
2071
  import * as zlib from "minizlib";
@@ -1571,13 +2091,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1571
2091
  decompress.flush(zlib.constants.Z_SYNC_FLUSH);
1572
2092
  const result = decompress.read();
1573
2093
  const jsonText = result.toString();
1574
- const json = JSON.parse(jsonText);
1575
2094
  let formattedMsg;
1576
- if (json.message.startsWith("{")) {
1577
- const ohmaMsg = JSON.parse(json.message);
2095
+ let jsonMessage;
2096
+ try {
2097
+ jsonMessage = JSON.parse(jsonText).message;
2098
+ } catch {
2099
+ jsonMessage = jsonText;
2100
+ }
2101
+ try {
2102
+ const ohmaMsg = JSON.parse(jsonMessage);
1578
2103
  formattedMsg = JSON.stringify(ohmaMsg, null, 2);
1579
- } else {
1580
- formattedMsg = json.message;
2104
+ } catch {
2105
+ formattedMsg = jsonMessage;
1581
2106
  }
1582
2107
  decodeResult.decoded = true;
1583
2108
  decodeResult.decoder.decodeLevel = "full";
@@ -1616,225 +2141,20 @@ var Label_H1_POS = class extends DecoderPlugin {
1616
2141
  decodeResult.formatted.description = "Position Report";
1617
2142
  decodeResult.message = message;
1618
2143
  decodeResult.remaining.text = "";
1619
- const checksum = message.text.slice(-4);
1620
- const header = findHeader(message.text.slice(0, -4));
1621
- const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1622
- const parts = message.text.replace(header, "").slice(0, -4).split(",");
1623
- if (parts.length == 1) {
1624
- if (decoded) {
1625
- processChecksum(decodeResult, checksum);
1626
- decodeResult.decoded = true;
1627
- decodeResult.decoder.decodeLevel = "full";
1628
- } else if (decodeResult.remaining.text.length > 0) {
1629
- processChecksum(decodeResult, checksum);
1630
- decodeResult.decoded = true;
1631
- decodeResult.decoder.decodeLevel = "partial";
1632
- } else {
1633
- decodeResult.decoded = false;
1634
- decodeResult.decoder.decodeLevel = "none";
1635
- }
1636
- } else if (parts.length === 10) {
1637
- processAlt(decodeResult, parts[3]);
1638
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1639
- processTemp(decodeResult, parts[7]);
1640
- processUnknown(decodeResult, parts[8]);
1641
- processUnknown(decodeResult, parts[9]);
1642
- processChecksum(decodeResult, checksum);
1643
- decodeResult.decoded = true;
1644
- decodeResult.decoder.decodeLevel = "partial";
1645
- } else if (parts.length === 11) {
1646
- processAlt(decodeResult, parts[3]);
1647
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1648
- processTemp(decodeResult, parts[7]);
1649
- processUnknown(decodeResult, parts[8]);
1650
- processUnknown(decodeResult, parts[9]);
1651
- processChecksum(decodeResult, checksum);
1652
- decodeResult.decoded = true;
1653
- decodeResult.decoder.decodeLevel = "partial";
1654
- } else if (parts.length === 12) {
1655
- const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1656
- processUnknown(decodeResult, parts[3]);
1657
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1658
- processTemp(decodeResult, parts[7]);
1659
- processUnknown(decodeResult, parts[8]);
1660
- processUnknown(decodeResult, parts[9]);
1661
- processUnknown(decodeResult, parts[10]);
1662
- processChecksum(decodeResult, checksum);
1663
- decodeResult.decoded = true;
1664
- decodeResult.decoder.decodeLevel = "partial";
1665
- } else if (parts.length === 14) {
1666
- processAlt(decodeResult, parts[3]);
1667
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1668
- processTemp(decodeResult, parts[7]);
1669
- processUnknown(decodeResult, parts[8]);
1670
- processUnknown(decodeResult, parts[9]);
1671
- processGndspd(decodeResult, parts[10]);
1672
- processUnknown(decodeResult, parts[11]);
1673
- processUnknown(decodeResult, parts[12]);
1674
- processUnknown(decodeResult, parts[13]);
1675
- processChecksum(decodeResult, checksum);
1676
- decodeResult.decoded = true;
1677
- decodeResult.decoder.decodeLevel = "partial";
1678
- } else if (parts.length === 15) {
1679
- decodeResult.raw.flight_number = parts[1];
1680
- let date = void 0;
1681
- if (parts[2].startsWith("/DC")) {
1682
- date = parts[2].substring(3);
1683
- } else {
1684
- processUnknown(decodeResult, parts[2]);
1685
- }
1686
- processUnknown(decodeResult, parts[3]);
1687
- const fields = parts[4].split("/");
1688
- for (let i = 0; i < fields.length; ++i) {
1689
- const field = fields[i];
1690
- if (field.startsWith("PS")) {
1691
- processPosition2(decodeResult, field.substring(2));
1692
- } else {
1693
- if (i === 0) {
1694
- processUnknown(decodeResult, field);
1695
- } else {
1696
- processUnknown(decodeResult, "/" + field);
1697
- }
1698
- }
1699
- }
1700
- processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
1701
- processAlt(decodeResult, parts[6]);
1702
- processTemp(decodeResult, parts[10]);
1703
- processUnknown(decodeResult, parts[11]);
1704
- processUnknown(decodeResult, parts[12]);
1705
- processUnknown(decodeResult, parts[13]);
1706
- processUnknown(decodeResult, parts[14]);
1707
- processChecksum(decodeResult, checksum);
1708
- decodeResult.decoded = true;
1709
- decodeResult.decoder.decodeLevel = "partial";
1710
- } else if (parts.length === 21) {
1711
- processRunway(decodeResult, parts[1]);
1712
- processUnknown(decodeResult, parts.slice(2, 11).join(","));
1713
- processTemp(decodeResult, parts[11]);
1714
- processUnknown(decodeResult, parts.slice(12, 20).join(","));
1715
- FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1716
- processChecksum(decodeResult, checksum);
1717
- decodeResult.decoded = true;
1718
- decodeResult.decoder.decodeLevel = "partial";
1719
- } else if (parts.length === 32) {
1720
- processRunway(decodeResult, parts[1]);
1721
- const time = parts[2];
1722
- processUnknown(decodeResult, parts[3]);
1723
- const past = parts[4];
1724
- processUnknown(decodeResult, parts[5]);
1725
- const eta = parts[6];
1726
- const next = parts[7];
1727
- processUnknown(decodeResult, parts.slice(8, 14).join(","));
1728
- processUnknown(decodeResult, parts[16]);
1729
- processUnknown(decodeResult, parts[17]);
1730
- processUnknown(decodeResult, parts[18]);
1731
- processGndspd(decodeResult, parts[19]);
1732
- processUnknown(decodeResult, parts[20]);
1733
- processUnknown(decodeResult, parts[21]);
1734
- processAlt(decodeResult, parts[22]);
1735
- processUnknown(decodeResult, parts.slice(23, 31).join(","));
1736
- const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1737
- processRoute(decodeResult, past, time, next, eta);
1738
- decodeResult.decoded = true;
1739
- decodeResult.decoder.decodeLevel = "partial";
1740
- } else {
1741
- if (options.debug) {
2144
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2145
+ decodeResult.decoded = true;
2146
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2147
+ if (decodeResult.formatted.items.length === 0) {
2148
+ if (options?.debug) {
1742
2149
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1743
2150
  }
1744
- decodeResult.remaining.text += message.text;
2151
+ decodeResult.remaining.text = message.text;
1745
2152
  decodeResult.decoded = false;
1746
2153
  decodeResult.decoder.decodeLevel = "none";
1747
2154
  }
1748
2155
  return decodeResult;
1749
2156
  }
1750
2157
  };
1751
- function processUnknown(decodeResult, value) {
1752
- decodeResult.remaining.text += "," + value;
1753
- }
1754
- function processPosition2(decodeResult, value) {
1755
- const position = CoordinateUtils.decodeStringCoordinates(value);
1756
- if (position) {
1757
- decodeResult.raw.position = position;
1758
- decodeResult.formatted.items.push({
1759
- type: "aircraft_position",
1760
- code: "POS",
1761
- label: "Aircraft Position",
1762
- value: CoordinateUtils.coordinateString(position)
1763
- });
1764
- }
1765
- }
1766
- function processAlt(decodeResult, value) {
1767
- decodeResult.raw.altitude = Number(value) * 100;
1768
- decodeResult.formatted.items.push({
1769
- type: "altitude",
1770
- code: "ALT",
1771
- label: "Altitude",
1772
- value: `${decodeResult.raw.altitude} feet`
1773
- });
1774
- }
1775
- function processTemp(decodeResult, value) {
1776
- decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1777
- decodeResult.formatted.items.push({
1778
- type: "outside_air_temperature",
1779
- code: "OATEMP",
1780
- label: "Outside Air Temperature (C)",
1781
- value: `${decodeResult.raw.outside_air_temperature}`
1782
- });
1783
- }
1784
- function processRunway(decodeResult, value) {
1785
- decodeResult.raw.arrival_runway = value.replace("RW", "");
1786
- decodeResult.formatted.items.push({
1787
- type: "runway",
1788
- label: "Arrival Runway",
1789
- value: decodeResult.raw.arrival_runway
1790
- });
1791
- }
1792
- function processGndspd(decodeResult, value) {
1793
- decodeResult.raw.groundspeed = Number(value);
1794
- decodeResult.formatted.items.push({
1795
- type: "aircraft_groundspeed",
1796
- code: "GSPD",
1797
- label: "Aircraft Groundspeed",
1798
- value: `${decodeResult.raw.groundspeed}`
1799
- });
1800
- }
1801
- function processRoute(decodeResult, last, time, next, eta, then, date) {
1802
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1803
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1804
- const timeFormat = date ? "epoch" : "tod";
1805
- const lastWaypoint = RouteUtils.getWaypoint(last);
1806
- lastWaypoint.time = lastTime;
1807
- lastWaypoint.timeFormat = timeFormat;
1808
- const nextWaypoint = RouteUtils.getWaypoint(next);
1809
- nextWaypoint.time = nextTime;
1810
- nextWaypoint.timeFormat = timeFormat;
1811
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1812
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1813
- decodeResult.raw.route = { waypoints };
1814
- decodeResult.formatted.items.push({
1815
- type: "aircraft_route",
1816
- code: "ROUTE",
1817
- label: "Aircraft Route",
1818
- value: RouteUtils.routeToString(decodeResult.raw.route)
1819
- });
1820
- }
1821
- function processChecksum(decodeResult, value) {
1822
- decodeResult.raw.checksum = Number("0x" + value);
1823
- decodeResult.formatted.items.push({
1824
- type: "message_checksum",
1825
- code: "CHECKSUM",
1826
- label: "Message Checksum",
1827
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1828
- });
1829
- }
1830
- function findHeader(text) {
1831
- const parts = text.split(",");
1832
- const header = parts[0];
1833
- if (header.indexOf("/TS") === -1) {
1834
- return header;
1835
- }
1836
- return parts[0] + "," + parts[1];
1837
- }
1838
2158
 
1839
2159
  // lib/plugins/Label_H1_WRN.ts
1840
2160
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -2989,6 +3309,7 @@ var MessageDecoder = class {
2989
3309
  this.registerPlugin(new Label_15_FST(this));
2990
3310
  this.registerPlugin(new Label_16_N_Space(this));
2991
3311
  this.registerPlugin(new Label_20_POS(this));
3312
+ this.registerPlugin(new Label_21_POS(this));
2992
3313
  this.registerPlugin(new Label_30_Slash_EA(this));
2993
3314
  this.registerPlugin(new Label_44_ETA(this));
2994
3315
  this.registerPlugin(new Label_44_IN(this));
@@ -2997,6 +3318,9 @@ var MessageDecoder = class {
2997
3318
  this.registerPlugin(new Label_44_POS(this));
2998
3319
  this.registerPlugin(new Label_B6_Forwardslash(this));
2999
3320
  this.registerPlugin(new Label_H1_FPN(this));
3321
+ this.registerPlugin(new Label_H1_FLR(this));
3322
+ this.registerPlugin(new Label_H1_FTX(this));
3323
+ this.registerPlugin(new Label_H1_INI(this));
3000
3324
  this.registerPlugin(new Label_H1_OHMA(this));
3001
3325
  this.registerPlugin(new Label_H1_POS(this));
3002
3326
  this.registerPlugin(new Label_H1_WRN(this));