@airframes/acars-decoder 1.6.6 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -53,20 +53,22 @@ var IcaoDecoder = class {
53
53
  var DecoderPlugin = class {
54
54
  decoder;
55
55
  name = "unknown";
56
- defaultResult = {
57
- decoded: false,
58
- decoder: {
59
- name: "unknown",
60
- type: "pattern-match",
61
- decodeLevel: "none"
62
- },
63
- formatted: {
64
- description: "Unknown",
65
- items: []
66
- },
67
- raw: {},
68
- remaining: {}
69
- };
56
+ defaultResult() {
57
+ return {
58
+ decoded: false,
59
+ decoder: {
60
+ name: "unknown",
61
+ type: "pattern-match",
62
+ decodeLevel: "none"
63
+ },
64
+ formatted: {
65
+ description: "Unknown",
66
+ items: []
67
+ },
68
+ raw: {},
69
+ remaining: {}
70
+ };
71
+ }
70
72
  options;
71
73
  constructor(decoder, options = {}) {
72
74
  this.decoder = decoder;
@@ -89,7 +91,7 @@ var DecoderPlugin = class {
89
91
  };
90
92
  }
91
93
  decode(message) {
92
- const decodeResult = this.defaultResult;
94
+ const decodeResult = this.defaultResult();
93
95
  decodeResult.remaining.text = message.text;
94
96
  return decodeResult;
95
97
  }
@@ -129,7 +131,7 @@ var Label_5Z = class extends DecoderPlugin {
129
131
  };
130
132
  }
131
133
  decode(message, options = {}) {
132
- const decodeResult = this.defaultResult;
134
+ const decodeResult = this.defaultResult();
133
135
  decodeResult.decoder.name = this.name;
134
136
  decodeResult.formatted.description = "Airline Designated Downlink";
135
137
  const uaRegex = /^\/(?<type>\w+) (?<remainder>.+)/;
@@ -206,6 +208,12 @@ var Label_5Z = class extends DecoderPlugin {
206
208
 
207
209
  // lib/utils/coordinate_utils.ts
208
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
+ */
209
217
  static decodeStringCoordinates(stringCoords) {
210
218
  var results = {};
211
219
  const firstChar = stringCoords.substring(0, 1);
@@ -223,6 +231,33 @@ var CoordinateUtils = class {
223
231
  }
224
232
  return results;
225
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
+ }
226
261
  static coordinateString(coords) {
227
262
  const latDir = coords.latitude > 0 ? "N" : "S";
228
263
  const lonDir = coords.longitude > 0 ? "E" : "W";
@@ -240,7 +275,7 @@ var Label_12_N_Space = class extends DecoderPlugin {
240
275
  };
241
276
  }
242
277
  decode(message, options = {}) {
243
- const decodeResult = this.defaultResult;
278
+ const decodeResult = this.defaultResult();
244
279
  decodeResult.decoder.name = this.name;
245
280
  decodeResult.formatted.description = "Position Report";
246
281
  decodeResult.message = message;
@@ -293,7 +328,7 @@ var Label_15 = class extends DecoderPlugin {
293
328
  };
294
329
  }
295
330
  decode(message, options = {}) {
296
- const decodeResult = this.defaultResult;
331
+ const decodeResult = this.defaultResult();
297
332
  decodeResult.decoder.name = this.name;
298
333
  decodeResult.formatted.description = "Position Report";
299
334
  const twoZeeRegex = /^\(2(?<between>.+)\(Z$/;
@@ -325,7 +360,7 @@ var Label_15_FST = class extends DecoderPlugin {
325
360
  };
326
361
  }
327
362
  decode(message, options = {}) {
328
- const decodeResult = this.defaultResult;
363
+ const decodeResult = this.defaultResult();
329
364
  decodeResult.decoder.name = this.name;
330
365
  decodeResult.formatted.description = "Position Report";
331
366
  decodeResult.message = message;
@@ -376,7 +411,7 @@ var Label_16_N_Space = class extends DecoderPlugin {
376
411
  };
377
412
  }
378
413
  decode(message, options = {}) {
379
- const decodeResult = this.defaultResult;
414
+ const decodeResult = this.defaultResult();
380
415
  decodeResult.decoder.name = this.name;
381
416
  decodeResult.formatted.description = "Position Report";
382
417
  decodeResult.message = message;
@@ -499,7 +534,7 @@ var Label_1M_Slash = class extends DecoderPlugin {
499
534
  };
500
535
  }
501
536
  decode(message, options = {}) {
502
- const decodeResult = this.defaultResult;
537
+ const decodeResult = this.defaultResult();
503
538
  decodeResult.decoder.name = this.name;
504
539
  decodeResult.formatted.description = "ETA Report";
505
540
  decodeResult.message = message;
@@ -549,7 +584,7 @@ var Label_20_POS = class extends DecoderPlugin {
549
584
  };
550
585
  }
551
586
  decode(message, options = {}) {
552
- const decodeResult = this.defaultResult;
587
+ const decodeResult = this.defaultResult();
553
588
  decodeResult.decoder.name = this.name;
554
589
  decodeResult.formatted.description = "Position Report";
555
590
  decodeResult.message = message;
@@ -593,6 +628,96 @@ var Label_20_POS = class extends DecoderPlugin {
593
628
  }
594
629
  };
595
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
+
596
721
  // lib/plugins/Label_30_Slash_EA.ts
597
722
  var Label_30_Slash_EA = class extends DecoderPlugin {
598
723
  name = "label-30-slash-ea";
@@ -603,7 +728,7 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
603
728
  };
604
729
  }
605
730
  decode(message, options = {}) {
606
- const decodeResult = this.defaultResult;
731
+ const decodeResult = this.defaultResult();
607
732
  decodeResult.decoder.name = this.name;
608
733
  decodeResult.formatted.description = "ETA Report";
609
734
  decodeResult.message = message;
@@ -648,7 +773,7 @@ var Label_44_ETA = class extends DecoderPlugin {
648
773
  };
649
774
  }
650
775
  decode(message, options = {}) {
651
- const decodeResult = this.defaultResult;
776
+ const decodeResult = this.defaultResult();
652
777
  decodeResult.decoder.name = this.name;
653
778
  decodeResult.formatted.description = "ETA Report";
654
779
  decodeResult.message = message;
@@ -705,7 +830,7 @@ var Label_44_IN = class extends DecoderPlugin {
705
830
  };
706
831
  }
707
832
  decode(message, options = {}) {
708
- const decodeResult = this.defaultResult;
833
+ const decodeResult = this.defaultResult();
709
834
  decodeResult.decoder.name = this.name;
710
835
  decodeResult.formatted.description = "In Air Report";
711
836
  decodeResult.message = message;
@@ -762,7 +887,7 @@ var Label_44_OFF = class extends DecoderPlugin {
762
887
  };
763
888
  }
764
889
  decode(message, options = {}) {
765
- const decodeResult = this.defaultResult;
890
+ const decodeResult = this.defaultResult();
766
891
  decodeResult.decoder.name = this.name;
767
892
  decodeResult.formatted.description = "Off Runway Report";
768
893
  decodeResult.message = message;
@@ -822,7 +947,7 @@ var Label_44_ON = class extends DecoderPlugin {
822
947
  };
823
948
  }
824
949
  decode(message, options = {}) {
825
- const decodeResult = this.defaultResult;
950
+ const decodeResult = this.defaultResult();
826
951
  decodeResult.decoder.name = this.name;
827
952
  decodeResult.formatted.description = "On Runway Report";
828
953
  decodeResult.message = message;
@@ -879,7 +1004,7 @@ var Label_44_POS = class extends DecoderPlugin {
879
1004
  };
880
1005
  }
881
1006
  decode(message, options = {}) {
882
- const decodeResult = this.defaultResult;
1007
+ const decodeResult = this.defaultResult();
883
1008
  decodeResult.decoder.name = this.name;
884
1009
  decodeResult.formatted.description = "Position Report";
885
1010
  decodeResult.message = message;
@@ -890,7 +1015,7 @@ var Label_44_POS = class extends DecoderPlugin {
890
1015
  console.log(`Label 44 Position Report: groups`);
891
1016
  console.log(results.groups);
892
1017
  }
893
- decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
1018
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
894
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);
895
1020
  decodeResult.raw.departure_icao = results.groups.departure_icao;
896
1021
  decodeResult.raw.arrival_icao = results.groups.arrival_icao;
@@ -905,9 +1030,9 @@ var Label_44_POS = class extends DecoderPlugin {
905
1030
  }
906
1031
  if (decodeResult.raw.position) {
907
1032
  decodeResult.formatted.items.push({
908
- type: "position",
1033
+ type: "aircraft_position",
909
1034
  code: "POS",
910
- label: "Position",
1035
+ label: "Aircraft Position",
911
1036
  value: CoordinateUtils.coordinateString(decodeResult.raw.position)
912
1037
  });
913
1038
  }
@@ -961,7 +1086,7 @@ var Label_80 = class extends DecoderPlugin {
961
1086
  };
962
1087
  }
963
1088
  decode(message, options = {}) {
964
- const decodeResult = this.defaultResult;
1089
+ const decodeResult = this.defaultResult();
965
1090
  decodeResult.decoder.name = this.name;
966
1091
  decodeResult.formatted.description = "Airline Defined Position Report";
967
1092
  const parts = message.text.split("\n");
@@ -1139,7 +1264,7 @@ var Label_8E = class extends DecoderPlugin {
1139
1264
  };
1140
1265
  }
1141
1266
  decode(message, options = {}) {
1142
- const decodeResult = this.defaultResult;
1267
+ const decodeResult = this.defaultResult();
1143
1268
  decodeResult.decoder.name = this.name;
1144
1269
  decodeResult.formatted.description = "ETA Report";
1145
1270
  decodeResult.message = message;
@@ -1180,7 +1305,7 @@ var Label_B6_Forwardslash = class extends DecoderPlugin {
1180
1305
  };
1181
1306
  }
1182
1307
  decode(message, options = {}) {
1183
- const decodeResult = this.defaultResult;
1308
+ const decodeResult = this.defaultResult();
1184
1309
  decodeResult.decoder.name = this.name;
1185
1310
  decodeResult.formatted.description = "CPDLC Message";
1186
1311
  decodeResult.message = message;
@@ -1200,7 +1325,7 @@ var Label_ColonComma = class extends DecoderPlugin {
1200
1325
  };
1201
1326
  }
1202
1327
  decode(message, options = {}) {
1203
- const decodeResult = this.defaultResult;
1328
+ const decodeResult = this.defaultResult();
1204
1329
  decodeResult.decoder.name = this.name;
1205
1330
  decodeResult.raw.frequency = Number(message.text) / 1e3;
1206
1331
  decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
@@ -1215,6 +1340,112 @@ var Label_ColonComma = class extends DecoderPlugin {
1215
1340
  }
1216
1341
  };
1217
1342
 
1343
+ // lib/utils/result_formatter.ts
1344
+ var ResultFormatter = class {
1345
+ static altitude(decodeResult, value) {
1346
+ decodeResult.raw.altitude = value;
1347
+ decodeResult.formatted.items.push({
1348
+ type: "altitude",
1349
+ code: "ALT",
1350
+ label: "Altitude",
1351
+ value: `${decodeResult.raw.altitude} feet`
1352
+ });
1353
+ }
1354
+ static flightNumber(decodeResult, value) {
1355
+ decodeResult.raw.flight_number = value;
1356
+ }
1357
+ static departureAirport(decodeResult, value) {
1358
+ decodeResult.raw.departure_icao = value;
1359
+ decodeResult.formatted.items.push({
1360
+ type: "origin",
1361
+ code: "ORG",
1362
+ label: "Origin",
1363
+ value: decodeResult.raw.departure_icao
1364
+ });
1365
+ }
1366
+ static departureRunway(decodeResult, value) {
1367
+ decodeResult.raw.departure_runway = value;
1368
+ decodeResult.formatted.items.push({
1369
+ type: "runway",
1370
+ code: "DEPRWY",
1371
+ label: "Departure Runway",
1372
+ value: decodeResult.raw.departure_runway
1373
+ });
1374
+ }
1375
+ static arrivalAirport(decodeResult, value) {
1376
+ decodeResult.raw.arrival_icao = value;
1377
+ decodeResult.formatted.items.push({
1378
+ type: "destination",
1379
+ code: "DST",
1380
+ label: "Destination",
1381
+ value: decodeResult.raw.arrival_icao
1382
+ });
1383
+ }
1384
+ static eta(decodeResult, value) {
1385
+ decodeResult.formatted.items.push({
1386
+ type: "eta",
1387
+ code: "ETA",
1388
+ label: "Estimated Time of Arrival",
1389
+ value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
1390
+ });
1391
+ }
1392
+ static arrivalRunway(decodeResult, value) {
1393
+ decodeResult.raw.arrival_runway = value;
1394
+ decodeResult.formatted.items.push({
1395
+ type: "runway",
1396
+ label: "Arrival Runway",
1397
+ value: decodeResult.raw.arrival_runway
1398
+ });
1399
+ }
1400
+ static currentFuel(decodeResult, value) {
1401
+ decodeResult.raw.fuel_on_board = value;
1402
+ decodeResult.formatted.items.push({
1403
+ type: "fuel_on_board",
1404
+ code: "FOB",
1405
+ label: "Fuel On Board",
1406
+ value: decodeResult.raw.fuel_on_board.toString()
1407
+ });
1408
+ }
1409
+ static remainingFuel(decodeResult, value) {
1410
+ decodeResult.raw.fuel_remaining = value;
1411
+ decodeResult.formatted.items.push({
1412
+ type: "fuel_remaining",
1413
+ label: "Fuel Remaining",
1414
+ value: decodeResult.raw.fuel_remaining.toString()
1415
+ });
1416
+ }
1417
+ static checksum(decodeResult, value) {
1418
+ decodeResult.raw.checksum = Number("0x" + value);
1419
+ decodeResult.formatted.items.push({
1420
+ type: "message_checksum",
1421
+ code: "CHECKSUM",
1422
+ label: "Message Checksum",
1423
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1424
+ });
1425
+ }
1426
+ static groundspeed(decodeResult, value) {
1427
+ decodeResult.raw.groundspeed = value;
1428
+ decodeResult.formatted.items.push({
1429
+ type: "aircraft_groundspeed",
1430
+ code: "GSPD",
1431
+ label: "Aircraft Groundspeed",
1432
+ value: `${decodeResult.raw.groundspeed}`
1433
+ });
1434
+ }
1435
+ static temperature(decodeResult, value) {
1436
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1437
+ decodeResult.formatted.items.push({
1438
+ type: "outside_air_temperature",
1439
+ code: "OATEMP",
1440
+ label: "Outside Air Temperature (C)",
1441
+ value: `${decodeResult.raw.outside_air_temperature}`
1442
+ });
1443
+ }
1444
+ static unknown(decodeResult, value) {
1445
+ decodeResult.remaining.text += "," + value;
1446
+ }
1447
+ };
1448
+
1218
1449
  // lib/utils/route_utils.ts
1219
1450
  var RouteUtils = class _RouteUtils {
1220
1451
  static routeToString(route) {
@@ -1255,13 +1486,13 @@ var RouteUtils = class _RouteUtils {
1255
1486
  }
1256
1487
  const waypoint = leg.split(",");
1257
1488
  if (waypoint.length == 2) {
1258
- const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1489
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
1259
1490
  if (position) {
1260
1491
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1261
1492
  }
1262
1493
  }
1263
1494
  if (leg.length == 13 || leg.length == 14) {
1264
- const position = CoordinateUtils.decodeStringCoordinates(leg);
1495
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
1265
1496
  const name = waypoint.length == 2 ? waypoint[0] : "";
1266
1497
  if (position) {
1267
1498
  return { name, latitude: position.latitude, longitude: position.longitude };
@@ -1287,7 +1518,7 @@ var RouteUtils = class _RouteUtils {
1287
1518
  };
1288
1519
 
1289
1520
  // lib/utils/flight_plan_utils.ts
1290
- var FlightPlanUtils = class {
1521
+ var FlightPlanUtils = class _FlightPlanUtils {
1291
1522
  /**
1292
1523
  * Processes flight plan data
1293
1524
  *
@@ -1298,7 +1529,7 @@ var FlightPlanUtils = class {
1298
1529
  * @returns whether all fields were processed or not
1299
1530
  */
1300
1531
  static processFlightPlan(decodeResult, data) {
1301
- let allKnownFields = parseHeader(decodeResult, data[0]);
1532
+ let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
1302
1533
  for (let i = 1; i < data.length; i += 2) {
1303
1534
  const key = data[i];
1304
1535
  const value = data[i + 1];
@@ -1338,60 +1569,9 @@ var FlightPlanUtils = class {
1338
1569
  }
1339
1570
  return allKnownFields;
1340
1571
  }
1341
- };
1342
- function parseMessageType(decodeResult, messageType) {
1343
- let decoded = true;
1344
- const parts = messageType.split("#");
1345
- if (parts.length == 1) {
1346
- if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1347
- decoded = processPosition(decodeResult, parts[0].substring(3));
1348
- }
1349
- return decoded;
1350
- } else if (parts.length == 2) {
1351
- if (parts[0].length > 0) {
1352
- decodeResult.remaining.text += parts[0].substring(0, 3);
1353
- decodeResult.raw.flight_number = parts[0].substring(3);
1354
- decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1355
- }
1356
- if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1357
- decoded = processPosition(decodeResult, parts[1].substring(6));
1358
- }
1359
- decodeResult.raw.message_type = messageType;
1360
- return decoded;
1361
- }
1362
- decodeResult.remaining.text += messageType;
1363
- return false;
1364
- }
1365
- function parseHeader(decodeResult, header) {
1366
- let allKnownFields = true;
1367
- const fields = header.split("/");
1368
- allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1369
- for (let i = 1; i < fields.length; ++i) {
1370
- if (fields[i].startsWith("FN")) {
1371
- decodeResult.raw.flight_number = fields[i].substring(2);
1372
- } else if (fields[i].startsWith("SN")) {
1373
- decodeResult.raw.serial_number = fields[i].substring(2);
1374
- } else if (fields[i].startsWith("TS")) {
1375
- const ts = fields[i].substring(2).split(",");
1376
- let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1377
- if (Number.isNaN(time)) {
1378
- const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1379
- time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1380
- }
1381
- decodeResult.raw.message_timestamp = time;
1382
- } else if (fields[i].startsWith("PS")) {
1383
- const pos = fields[i].substring(2);
1384
- allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1385
- } else if (fields[i].startsWith("DT")) {
1386
- const icao = fields[i].substring(2);
1387
- decodeResult.raw.arrival_icao = icao;
1388
- decodeResult.formatted.items.push({
1389
- type: "destination",
1390
- code: "DST",
1391
- label: "Destination",
1392
- value: decodeResult.raw.arrival_icao
1393
- });
1394
- } else if (fields[i].startsWith("RF")) {
1572
+ static parseHeader(decodeResult, header) {
1573
+ let allKnownFields = true;
1574
+ if (header.startsWith("RF")) {
1395
1575
  decodeResult.formatted.items.push({
1396
1576
  type: "status",
1397
1577
  code: "ROUTE_STATUS",
@@ -1399,10 +1579,10 @@ function parseHeader(decodeResult, header) {
1399
1579
  value: "Route Filed"
1400
1580
  });
1401
1581
  decodeResult.raw.route_status = "RF";
1402
- if (fields[i].length > 2) {
1403
- addRoute(decodeResult, fields[i].substring(2));
1582
+ if (header.length > 2) {
1583
+ addRoute(decodeResult, header.substring(2));
1404
1584
  }
1405
- } else if (fields[i] == "RP") {
1585
+ } else if (header.startsWith("RP")) {
1406
1586
  decodeResult.raw.route_status = "RP";
1407
1587
  decodeResult.formatted.items.push({
1408
1588
  type: "status",
@@ -1410,8 +1590,8 @@ function parseHeader(decodeResult, header) {
1410
1590
  label: "Route Status",
1411
1591
  value: "Route Planned"
1412
1592
  });
1413
- decodeResult.raw.route_status = fields[i];
1414
- } else if (fields[i] == "RI") {
1593
+ decodeResult.raw.route_status = header;
1594
+ } else if (header.startsWith("RI")) {
1415
1595
  decodeResult.raw.route_status = "RI";
1416
1596
  decodeResult.formatted.items.push({
1417
1597
  type: "status",
@@ -1420,58 +1600,23 @@ function parseHeader(decodeResult, header) {
1420
1600
  value: "Route Inactive"
1421
1601
  });
1422
1602
  } else {
1423
- decodeResult.remaining.text += "/" + fields[i];
1603
+ decodeResult.remaining.text += header;
1424
1604
  allKnownFields = false;
1425
1605
  }
1606
+ return allKnownFields;
1426
1607
  }
1427
- return allKnownFields;
1428
- }
1429
- function processPosition(decodeResult, value) {
1430
- const position = CoordinateUtils.decodeStringCoordinates(value);
1431
- if (position) {
1432
- decodeResult.raw.position = position;
1433
- decodeResult.formatted.items.push({
1434
- type: "aircraft_position",
1435
- code: "POS",
1436
- label: "Aircraft Position",
1437
- value: CoordinateUtils.coordinateString(position)
1438
- });
1439
- }
1440
- return !!position;
1441
- }
1608
+ };
1442
1609
  function addArrivalAirport(decodeResult, value) {
1443
- decodeResult.raw.arrival_icao = value;
1444
- decodeResult.formatted.items.push({
1445
- type: "destination",
1446
- code: "DST",
1447
- label: "Destination",
1448
- value: decodeResult.raw.arrival_icao
1449
- });
1610
+ ResultFormatter.arrivalAirport(decodeResult, value);
1450
1611
  }
1451
1612
  function addDepartureAirport(decodeResult, value) {
1452
- decodeResult.raw.departure_icao = value;
1453
- decodeResult.formatted.items.push({
1454
- type: "origin",
1455
- code: "ORG",
1456
- label: "Origin",
1457
- value: decodeResult.raw.departure_icao
1458
- });
1613
+ ResultFormatter.departureAirport(decodeResult, value);
1459
1614
  }
1460
1615
  function addRunway(decodeResult, value) {
1461
1616
  if (value.length === 8) {
1462
- decodeResult.raw.arrival_runway = value.substring(4, 7);
1463
- decodeResult.formatted.items.push({
1464
- type: "runway",
1465
- label: "Arrival Runway",
1466
- value: decodeResult.raw.arrival_runway
1467
- });
1617
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1468
1618
  }
1469
- decodeResult.raw.departure_runway = value.substring(0, 3);
1470
- decodeResult.formatted.items.push({
1471
- type: "runway",
1472
- label: "Departure Runway",
1473
- value: decodeResult.raw.departure_runway
1474
- });
1619
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1475
1620
  }
1476
1621
  function addRoute(decodeResult, value) {
1477
1622
  const route = value.split(".");
@@ -1531,6 +1676,241 @@ function addCompanyRoute(decodeResult, value) {
1531
1676
  });
1532
1677
  }
1533
1678
 
1679
+ // lib/utils/h1_helper.ts
1680
+ var H1Helper = class {
1681
+ static decodeH1Message(decodeResult, message) {
1682
+ let allKnownFields = true;
1683
+ const checksum = message.slice(-4);
1684
+ const data = message.slice(0, message.length - 4);
1685
+ const fields = data.split("/");
1686
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1687
+ for (let i = 1; i < fields.length; ++i) {
1688
+ if (fields[i].startsWith("FN")) {
1689
+ decodeResult.raw.flight_number = fields[i].substring(2);
1690
+ } else if (fields[i].startsWith("SN")) {
1691
+ decodeResult.raw.serial_number = fields[i].substring(2);
1692
+ } else if (fields[i].startsWith("DC")) {
1693
+ processDC(decodeResult, fields[i].substring(2).split(","));
1694
+ } else if (fields[i].startsWith("TS")) {
1695
+ const ts = fields[i].substring(2).split(",");
1696
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1697
+ if (Number.isNaN(time)) {
1698
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1699
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1700
+ }
1701
+ decodeResult.raw.message_date = ts[1];
1702
+ decodeResult.raw.message_timestamp = time;
1703
+ } else if (fields[i].startsWith("PS")) {
1704
+ const pos = processPS(decodeResult, fields[i].substring(2).split(","));
1705
+ allKnownFields == allKnownFields && pos;
1706
+ } else if (fields[i].startsWith("DT")) {
1707
+ const data2 = fields[i].substring(2).split(",");
1708
+ const dt = processDT(decodeResult, data2);
1709
+ allKnownFields = allKnownFields && dt;
1710
+ } else if (fields[i].startsWith("ID")) {
1711
+ const data2 = fields[i].substring(2).split(",");
1712
+ decodeResult.raw.tail = data2[0];
1713
+ decodeResult.formatted.items.push({
1714
+ type: "tail",
1715
+ code: "TAIL",
1716
+ label: "Tail",
1717
+ value: decodeResult.raw.tail
1718
+ });
1719
+ if (data2.length > 1) {
1720
+ decodeResult.raw.flight_number = data2[1];
1721
+ }
1722
+ if (data2.length > 2) {
1723
+ allKnownFields = false;
1724
+ decodeResult.remaining.text += "," + data2.slice(2).join(",");
1725
+ }
1726
+ } else if (fields[i].startsWith("LR")) {
1727
+ const data2 = fields[i].substring(2).split(",");
1728
+ const lr = processLR(decodeResult, data2);
1729
+ allKnownFields = allKnownFields && lr;
1730
+ } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1731
+ const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1732
+ allKnownFields = allKnownFields && fp;
1733
+ } else if (fields[i].startsWith("PR")) {
1734
+ allKnownFields = false;
1735
+ decodeResult.remaining.text += "/" + fields[i];
1736
+ } else if (fields[i].startsWith("PS")) {
1737
+ allKnownFields = false;
1738
+ decodeResult.remaining.text += fields[i];
1739
+ } else {
1740
+ decodeResult.remaining.text += "/" + fields[i];
1741
+ allKnownFields = false;
1742
+ }
1743
+ }
1744
+ if (decodeResult.formatted.items.length > 0) {
1745
+ ResultFormatter.checksum(decodeResult, checksum);
1746
+ }
1747
+ return allKnownFields;
1748
+ }
1749
+ };
1750
+ function processDT(decodeResult, data) {
1751
+ let allKnownFields = true;
1752
+ if (!decodeResult.raw.arrival_icao) {
1753
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
1754
+ } else if (decodeResult.raw.arrival_icao != data[0]) {
1755
+ decodeResult.remaining.text += "/" + data;
1756
+ }
1757
+ if (data.length > 1) {
1758
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
1759
+ }
1760
+ if (data.length > 2) {
1761
+ ResultFormatter.currentFuel(decodeResult, Number(data[2]));
1762
+ }
1763
+ if (data.length > 3) {
1764
+ ResultFormatter.eta(decodeResult, data[3]);
1765
+ }
1766
+ if (data.length > 4) {
1767
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
1768
+ }
1769
+ if (data.length > 5) {
1770
+ allKnownFields = false;
1771
+ decodeResult.remaining.text += "," + data.slice(5).join(",");
1772
+ }
1773
+ return allKnownFields;
1774
+ }
1775
+ function processLR(decodeResult, data) {
1776
+ let allKnownFields = true;
1777
+ if (data.length === 19) {
1778
+ ResultFormatter.unknown(decodeResult, data[1]);
1779
+ ResultFormatter.flightNumber(decodeResult, data[2]);
1780
+ ResultFormatter.departureAirport(decodeResult, data[3]);
1781
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
1782
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
1783
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
1784
+ allKnownFields = false;
1785
+ } else {
1786
+ allKnownFields = false;
1787
+ }
1788
+ return allKnownFields;
1789
+ }
1790
+ function parseMessageType(decodeResult, messageType) {
1791
+ let decoded = true;
1792
+ const parts = messageType.split("#");
1793
+ if (parts.length == 1) {
1794
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1795
+ decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
1796
+ }
1797
+ return decoded;
1798
+ } else if (parts.length == 2) {
1799
+ if (parts[0].length > 0) {
1800
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1801
+ decodeResult.raw.flight_number = parts[0].substring(3);
1802
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1803
+ }
1804
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1805
+ decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
1806
+ }
1807
+ decodeResult.raw.message_type = messageType;
1808
+ return decoded;
1809
+ }
1810
+ decodeResult.remaining.text += messageType;
1811
+ return false;
1812
+ }
1813
+ function processDC(decodeResult, data) {
1814
+ decodeResult.raw.message_date = data[0];
1815
+ if (data.length === 1) {
1816
+ } else if (data.length === 2) {
1817
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
1818
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
1819
+ decodeResult.raw.message_timestamp = time;
1820
+ } else {
1821
+ return false;
1822
+ }
1823
+ return true;
1824
+ }
1825
+ function processPS(decodeResult, data) {
1826
+ let allKnownFields = true;
1827
+ const position = CoordinateUtils.decodeStringCoordinates(data[0]);
1828
+ if (position) {
1829
+ decodeResult.raw.position = position;
1830
+ decodeResult.formatted.items.push({
1831
+ type: "aircraft_position",
1832
+ code: "POS",
1833
+ label: "Aircraft Position",
1834
+ value: CoordinateUtils.coordinateString(position)
1835
+ });
1836
+ } else {
1837
+ allKnownFields = false;
1838
+ }
1839
+ console.log("PS data.length: ", data.length);
1840
+ console.log("PS data: ", data);
1841
+ if (data.length === 9) {
1842
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
1843
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
1844
+ ResultFormatter.temperature(decodeResult, data[6]);
1845
+ ResultFormatter.unknown(decodeResult, data[7]);
1846
+ ResultFormatter.unknown(decodeResult, data[8]);
1847
+ }
1848
+ if (data.length === 14) {
1849
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1850
+ processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
1851
+ ResultFormatter.temperature(decodeResult, data[7]);
1852
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1853
+ ResultFormatter.unknown(decodeResult, data[1]);
1854
+ ResultFormatter.unknown(decodeResult, data[8]);
1855
+ ResultFormatter.unknown(decodeResult, data[9]);
1856
+ ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
1857
+ }
1858
+ allKnownFields = false;
1859
+ return allKnownFields;
1860
+ }
1861
+ function processPosition2(decodeResult, data) {
1862
+ let allKnownFields = true;
1863
+ const position = CoordinateUtils.decodeStringCoordinates(data[0]);
1864
+ if (position) {
1865
+ decodeResult.raw.position = position;
1866
+ decodeResult.formatted.items.push({
1867
+ type: "aircraft_position",
1868
+ code: "POS",
1869
+ label: "Aircraft Position",
1870
+ value: CoordinateUtils.coordinateString(position)
1871
+ });
1872
+ } else {
1873
+ allKnownFields = false;
1874
+ }
1875
+ console.log("data.length: ", data.length);
1876
+ console.log("data: ", data);
1877
+ if (data.length >= 10) {
1878
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1879
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1880
+ ResultFormatter.temperature(decodeResult, data[7]);
1881
+ ResultFormatter.unknown(decodeResult, data[8]);
1882
+ ResultFormatter.unknown(decodeResult, data[9]);
1883
+ }
1884
+ if (data.length >= 14) {
1885
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1886
+ ResultFormatter.unknown(decodeResult, data[11]);
1887
+ ResultFormatter.unknown(decodeResult, data[12]);
1888
+ ResultFormatter.unknown(decodeResult, data[13]);
1889
+ }
1890
+ allKnownFields = false;
1891
+ return allKnownFields;
1892
+ }
1893
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1894
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1895
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1896
+ const timeFormat = date ? "epoch" : "tod";
1897
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1898
+ lastWaypoint.time = lastTime;
1899
+ lastWaypoint.timeFormat = timeFormat;
1900
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1901
+ nextWaypoint.time = nextTime;
1902
+ nextWaypoint.timeFormat = timeFormat;
1903
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1904
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1905
+ decodeResult.raw.route = { waypoints };
1906
+ decodeResult.formatted.items.push({
1907
+ type: "aircraft_route",
1908
+ code: "ROUTE",
1909
+ label: "Aircraft Route",
1910
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1911
+ });
1912
+ }
1913
+
1534
1914
  // lib/plugins/Label_H1_FPN.ts
1535
1915
  var Label_H1_FPN = class extends DecoderPlugin {
1536
1916
  name = "label-h1-fpn";
@@ -1541,19 +1921,16 @@ var Label_H1_FPN = class extends DecoderPlugin {
1541
1921
  };
1542
1922
  }
1543
1923
  decode(message, options = {}) {
1544
- let decodeResult = this.defaultResult;
1924
+ let decodeResult = this.defaultResult();
1545
1925
  decodeResult.decoder.name = this.name;
1546
1926
  decodeResult.formatted.description = "Flight Plan";
1547
1927
  decodeResult.message = message;
1928
+ decodeResult.remaining.text = "";
1548
1929
  const msg = message.text.replace(/\n|\r/g, "");
1549
- const checksum = msg.slice(-4);
1550
- const data = msg.slice(0, msg.length - 4).split(":");
1551
- if (data.length > 1) {
1552
- const fulllyDecoded = FlightPlanUtils.processFlightPlan(decodeResult, data);
1553
- addChecksum(decodeResult, checksum);
1554
- decodeResult.decoded = true;
1555
- decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1556
- } else {
1930
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
1931
+ decodeResult.decoded = true;
1932
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1933
+ if (decodeResult.formatted.items.length === 0) {
1557
1934
  if (options?.debug) {
1558
1935
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1559
1936
  }
@@ -1564,15 +1941,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
1564
1941
  return decodeResult;
1565
1942
  }
1566
1943
  };
1567
- function addChecksum(decodeResult, value) {
1568
- decodeResult.raw.checksum = Number("0x" + value);
1569
- decodeResult.formatted.items.push({
1570
- type: "message_checksum",
1571
- code: "CHECKSUM",
1572
- label: "Message Checksum",
1573
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1574
- });
1575
- }
1576
1944
 
1577
1945
  // lib/plugins/Label_H1_OHMA.ts
1578
1946
  var zlib = __toESM(require("minizlib"));
@@ -1585,7 +1953,7 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1585
1953
  };
1586
1954
  }
1587
1955
  decode(message, options = {}) {
1588
- let decodeResult = this.defaultResult;
1956
+ let decodeResult = this.defaultResult();
1589
1957
  decodeResult.decoder.name = this.name;
1590
1958
  decodeResult.formatted.description = "OHMA Message";
1591
1959
  decodeResult.message = message;
@@ -1598,13 +1966,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1598
1966
  decompress.flush(zlib.constants.Z_SYNC_FLUSH);
1599
1967
  const result = decompress.read();
1600
1968
  const jsonText = result.toString();
1601
- const json = JSON.parse(jsonText);
1602
1969
  let formattedMsg;
1603
- if (json.message.startsWith("{")) {
1604
- const ohmaMsg = JSON.parse(json.message);
1970
+ let jsonMessage;
1971
+ try {
1972
+ jsonMessage = JSON.parse(jsonText).message;
1973
+ } catch {
1974
+ jsonMessage = jsonText;
1975
+ }
1976
+ try {
1977
+ const ohmaMsg = JSON.parse(jsonMessage);
1605
1978
  formattedMsg = JSON.stringify(ohmaMsg, null, 2);
1606
- } else {
1607
- formattedMsg = json.message;
1979
+ } catch {
1980
+ formattedMsg = jsonMessage;
1608
1981
  }
1609
1982
  decodeResult.decoded = true;
1610
1983
  decodeResult.decoder.decodeLevel = "full";
@@ -1632,236 +2005,31 @@ var Label_H1_POS = class extends DecoderPlugin {
1632
2005
  name = "label-h1-pos";
1633
2006
  qualifiers() {
1634
2007
  return {
1635
- labels: ["H1"],
2008
+ labels: ["H1", "4J"],
1636
2009
  preambles: ["POS", "#M1BPOS", "/.POS"]
1637
2010
  //TODO - support data before #
1638
2011
  };
1639
2012
  }
1640
2013
  decode(message, options = {}) {
1641
- let decodeResult = this.defaultResult;
2014
+ let decodeResult = this.defaultResult();
1642
2015
  decodeResult.decoder.name = this.name;
1643
2016
  decodeResult.formatted.description = "Position Report";
1644
2017
  decodeResult.message = message;
1645
2018
  decodeResult.remaining.text = "";
1646
- const checksum = message.text.slice(-4);
1647
- const header = findHeader(message.text.slice(0, -4));
1648
- const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1649
- const parts = message.text.replace(header, "").slice(0, -4).split(",");
1650
- if (parts.length == 1) {
1651
- if (decoded) {
1652
- processChecksum(decodeResult, checksum);
1653
- decodeResult.decoded = true;
1654
- decodeResult.decoder.decodeLevel = "full";
1655
- } else if (decodeResult.remaining.text.length > 0) {
1656
- processChecksum(decodeResult, checksum);
1657
- decodeResult.decoded = true;
1658
- decodeResult.decoder.decodeLevel = "partial";
1659
- } else {
1660
- decodeResult.decoded = false;
1661
- decodeResult.decoder.decodeLevel = "none";
1662
- }
1663
- } else if (parts.length === 10) {
1664
- processAlt(decodeResult, parts[3]);
1665
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1666
- processTemp(decodeResult, parts[7]);
1667
- processUnknown(decodeResult, parts[8]);
1668
- processUnknown(decodeResult, parts[9]);
1669
- processChecksum(decodeResult, checksum);
1670
- decodeResult.decoded = true;
1671
- decodeResult.decoder.decodeLevel = "partial";
1672
- } else if (parts.length === 11) {
1673
- processAlt(decodeResult, parts[3]);
1674
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1675
- processTemp(decodeResult, parts[7]);
1676
- processUnknown(decodeResult, parts[8]);
1677
- processUnknown(decodeResult, parts[9]);
1678
- processChecksum(decodeResult, checksum);
1679
- decodeResult.decoded = true;
1680
- decodeResult.decoder.decodeLevel = "partial";
1681
- } else if (parts.length === 12) {
1682
- const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1683
- processUnknown(decodeResult, parts[3]);
1684
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1685
- processTemp(decodeResult, parts[7]);
1686
- processUnknown(decodeResult, parts[8]);
1687
- processUnknown(decodeResult, parts[9]);
1688
- processUnknown(decodeResult, parts[10]);
1689
- processChecksum(decodeResult, checksum);
1690
- decodeResult.decoded = true;
1691
- decodeResult.decoder.decodeLevel = "partial";
1692
- } else if (parts.length === 14) {
1693
- processAlt(decodeResult, parts[3]);
1694
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1695
- processTemp(decodeResult, parts[7]);
1696
- processUnknown(decodeResult, parts[8]);
1697
- processUnknown(decodeResult, parts[9]);
1698
- processGndspd(decodeResult, parts[10]);
1699
- processUnknown(decodeResult, parts[11]);
1700
- processUnknown(decodeResult, parts[12]);
1701
- processUnknown(decodeResult, parts[13]);
1702
- processChecksum(decodeResult, checksum);
1703
- decodeResult.decoded = true;
1704
- decodeResult.decoder.decodeLevel = "partial";
1705
- } else if (parts.length === 15) {
1706
- processUnknown(decodeResult, parts[1]);
1707
- let date = void 0;
1708
- if (parts[2].startsWith("/DC")) {
1709
- date = parts[2].substring(3);
1710
- } else {
1711
- processUnknown(decodeResult, parts[2]);
1712
- }
1713
- processUnknown(decodeResult, parts[3]);
1714
- const fields = parts[4].split("/");
1715
- for (let i = 0; i < fields.length; ++i) {
1716
- const field = fields[i];
1717
- if (field.startsWith("PS")) {
1718
- processPosition2(decodeResult, field.substring(2));
1719
- } else {
1720
- if (i === 0) {
1721
- processUnknown(decodeResult, field);
1722
- } else {
1723
- processUnknown(decodeResult, "/" + field);
1724
- }
1725
- }
1726
- }
1727
- processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
1728
- processAlt(decodeResult, parts[6]);
1729
- processTemp(decodeResult, parts[10]);
1730
- processUnknown(decodeResult, parts[11]);
1731
- processUnknown(decodeResult, parts[12]);
1732
- processUnknown(decodeResult, parts[13]);
1733
- processUnknown(decodeResult, parts[14]);
1734
- processChecksum(decodeResult, checksum);
1735
- decodeResult.decoded = true;
1736
- decodeResult.decoder.decodeLevel = "partial";
1737
- } else if (parts.length === 21) {
1738
- processRunway(decodeResult, parts[1]);
1739
- processUnknown(decodeResult, parts.slice(2, 11).join(","));
1740
- processTemp(decodeResult, parts[11]);
1741
- processUnknown(decodeResult, parts.slice(12, 20).join(","));
1742
- FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1743
- processChecksum(decodeResult, checksum);
1744
- decodeResult.decoded = true;
1745
- decodeResult.decoder.decodeLevel = "partial";
1746
- } else if (parts.length === 32) {
1747
- processRunway(decodeResult, parts[1]);
1748
- const time = parts[2];
1749
- processUnknown(decodeResult, parts[3]);
1750
- const past = parts[4];
1751
- processUnknown(decodeResult, parts[5]);
1752
- const eta = parts[6];
1753
- const next = parts[7];
1754
- processUnknown(decodeResult, parts.slice(8, 14).join(","));
1755
- processUnknown(decodeResult, parts[16]);
1756
- processUnknown(decodeResult, parts[17]);
1757
- processUnknown(decodeResult, parts[18]);
1758
- processGndspd(decodeResult, parts[19]);
1759
- processUnknown(decodeResult, parts[20]);
1760
- processUnknown(decodeResult, parts[21]);
1761
- processAlt(decodeResult, parts[22]);
1762
- processUnknown(decodeResult, parts.slice(23, 31).join(","));
1763
- const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1764
- processRoute(decodeResult, past, time, next, eta);
1765
- decodeResult.decoded = true;
1766
- decodeResult.decoder.decodeLevel = "partial";
1767
- } else {
1768
- if (options.debug) {
2019
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
2020
+ decodeResult.decoded = true;
2021
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
2022
+ if (decodeResult.formatted.items.length === 0) {
2023
+ if (options?.debug) {
1769
2024
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1770
2025
  }
1771
- decodeResult.remaining.text += message.text;
2026
+ decodeResult.remaining.text = message.text;
1772
2027
  decodeResult.decoded = false;
1773
2028
  decodeResult.decoder.decodeLevel = "none";
1774
2029
  }
1775
2030
  return decodeResult;
1776
2031
  }
1777
2032
  };
1778
- function processUnknown(decodeResult, value) {
1779
- decodeResult.remaining.text += "," + value;
1780
- }
1781
- function processPosition2(decodeResult, value) {
1782
- const position = CoordinateUtils.decodeStringCoordinates(value);
1783
- if (position) {
1784
- decodeResult.raw.position = position;
1785
- decodeResult.formatted.items.push({
1786
- type: "aircraft_position",
1787
- code: "POS",
1788
- label: "Aircraft Position",
1789
- value: CoordinateUtils.coordinateString(position)
1790
- });
1791
- }
1792
- }
1793
- function processAlt(decodeResult, value) {
1794
- decodeResult.raw.altitude = Number(value) * 100;
1795
- decodeResult.formatted.items.push({
1796
- type: "altitude",
1797
- code: "ALT",
1798
- label: "Altitude",
1799
- value: `${decodeResult.raw.altitude} feet`
1800
- });
1801
- }
1802
- function processTemp(decodeResult, value) {
1803
- decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1804
- decodeResult.formatted.items.push({
1805
- type: "outside_air_temperature",
1806
- code: "OATEMP",
1807
- label: "Outside Air Temperature (C)",
1808
- value: `${decodeResult.raw.outside_air_temperature}`
1809
- });
1810
- }
1811
- function processRunway(decodeResult, value) {
1812
- decodeResult.raw.arrival_runway = value.replace("RW", "");
1813
- decodeResult.formatted.items.push({
1814
- type: "runway",
1815
- label: "Arrival Runway",
1816
- value: decodeResult.raw.arrival_runway
1817
- });
1818
- }
1819
- function processGndspd(decodeResult, value) {
1820
- decodeResult.raw.groundspeed = Number(value);
1821
- decodeResult.formatted.items.push({
1822
- type: "aircraft_groundspeed",
1823
- code: "GSPD",
1824
- label: "Aircraft Groundspeed",
1825
- value: `${decodeResult.raw.groundspeed}`
1826
- });
1827
- }
1828
- function processRoute(decodeResult, last, time, next, eta, then, date) {
1829
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1830
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1831
- const timeFormat = date ? "epoch" : "tod";
1832
- const lastWaypoint = RouteUtils.getWaypoint(last);
1833
- lastWaypoint.time = lastTime;
1834
- lastWaypoint.timeFormat = timeFormat;
1835
- const nextWaypoint = RouteUtils.getWaypoint(next);
1836
- nextWaypoint.time = nextTime;
1837
- nextWaypoint.timeFormat = timeFormat;
1838
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1839
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1840
- decodeResult.raw.route = { waypoints };
1841
- decodeResult.formatted.items.push({
1842
- type: "aircraft_route",
1843
- code: "ROUTE",
1844
- label: "Aircraft Route",
1845
- value: RouteUtils.routeToString(decodeResult.raw.route)
1846
- });
1847
- }
1848
- function processChecksum(decodeResult, value) {
1849
- decodeResult.raw.checksum = Number("0x" + value);
1850
- decodeResult.formatted.items.push({
1851
- type: "message_checksum",
1852
- code: "CHECKSUM",
1853
- label: "Message Checksum",
1854
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1855
- });
1856
- }
1857
- function findHeader(text) {
1858
- const parts = text.split(",");
1859
- const header = parts[0];
1860
- if (header.indexOf("/TS") === -1) {
1861
- return header;
1862
- }
1863
- return parts[0] + "," + parts[1];
1864
- }
1865
2033
 
1866
2034
  // lib/plugins/Label_H1_WRN.ts
1867
2035
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -1873,7 +2041,7 @@ var Label_H1_WRN = class extends DecoderPlugin {
1873
2041
  };
1874
2042
  }
1875
2043
  decode(message, options = {}) {
1876
- let decodeResult = this.defaultResult;
2044
+ let decodeResult = this.defaultResult();
1877
2045
  decodeResult.decoder.name = this.name;
1878
2046
  decodeResult.formatted.description = "Warning Message";
1879
2047
  decodeResult.message = message;
@@ -1884,16 +2052,16 @@ var Label_H1_WRN = class extends DecoderPlugin {
1884
2052
  for (let i = 1; i < fields.length; i++) {
1885
2053
  const field = fields[i];
1886
2054
  if (field.startsWith("PN")) {
1887
- processUnknown2(decodeResult, "/" + field);
2055
+ processUnknown(decodeResult, "/" + field);
1888
2056
  } else {
1889
- processUnknown2(decodeResult, "/" + field);
2057
+ processUnknown(decodeResult, "/" + field);
1890
2058
  }
1891
2059
  }
1892
2060
  const data = parts[1].substring(0, 20);
1893
2061
  const msg = parts[1].substring(20);
1894
2062
  const datetime = data.substring(0, 12);
1895
2063
  const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
1896
- processUnknown2(decodeResult, data.substring(12));
2064
+ processUnknown(decodeResult, data.substring(12));
1897
2065
  decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
1898
2066
  decodeResult.raw.warning_message = msg;
1899
2067
  decodeResult.formatted.items.push({
@@ -1915,7 +2083,7 @@ var Label_H1_WRN = class extends DecoderPlugin {
1915
2083
  return decodeResult;
1916
2084
  }
1917
2085
  };
1918
- function processUnknown2(decodeResult, value) {
2086
+ function processUnknown(decodeResult, value) {
1919
2087
  decodeResult.remaining.text += value;
1920
2088
  }
1921
2089
 
@@ -1928,7 +2096,7 @@ var Label_SQ = class extends DecoderPlugin {
1928
2096
  };
1929
2097
  }
1930
2098
  decode(message, options = {}) {
1931
- const decodeResult = this.defaultResult;
2099
+ const decodeResult = this.defaultResult();
1932
2100
  decodeResult.decoder.name = this.name;
1933
2101
  decodeResult.raw.preamble = message.text.substring(0, 4);
1934
2102
  decodeResult.raw.version = message.text.substring(1, 2);
@@ -2027,7 +2195,7 @@ var Label_QR = class extends DecoderPlugin {
2027
2195
  };
2028
2196
  }
2029
2197
  decode(message, options = {}) {
2030
- const decodeResult = this.defaultResult;
2198
+ const decodeResult = this.defaultResult();
2031
2199
  decodeResult.decoder.name = this.name;
2032
2200
  decodeResult.raw.origin = message.text.substring(0, 4);
2033
2201
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2072,7 +2240,7 @@ var Label_QP = class extends DecoderPlugin {
2072
2240
  };
2073
2241
  }
2074
2242
  decode(message, options = {}) {
2075
- const decodeResult = this.defaultResult;
2243
+ const decodeResult = this.defaultResult();
2076
2244
  decodeResult.decoder.name = this.name;
2077
2245
  decodeResult.raw.origin = message.text.substring(0, 4);
2078
2246
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2117,7 +2285,7 @@ var Label_QS = class extends DecoderPlugin {
2117
2285
  };
2118
2286
  }
2119
2287
  decode(message, options = {}) {
2120
- const decodeResult = this.defaultResult;
2288
+ const decodeResult = this.defaultResult();
2121
2289
  decodeResult.decoder.name = this.name;
2122
2290
  decodeResult.raw.origin = message.text.substring(0, 4);
2123
2291
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2162,7 +2330,7 @@ var Label_QQ = class extends DecoderPlugin {
2162
2330
  };
2163
2331
  }
2164
2332
  decode(message, options = {}) {
2165
- const decodeResult = this.defaultResult;
2333
+ const decodeResult = this.defaultResult();
2166
2334
  decodeResult.decoder.name = this.name;
2167
2335
  decodeResult.raw.origin = message.text.substring(0, 4);
2168
2336
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -3016,6 +3184,7 @@ var MessageDecoder = class {
3016
3184
  this.registerPlugin(new Label_15_FST(this));
3017
3185
  this.registerPlugin(new Label_16_N_Space(this));
3018
3186
  this.registerPlugin(new Label_20_POS(this));
3187
+ this.registerPlugin(new Label_21_POS(this));
3019
3188
  this.registerPlugin(new Label_30_Slash_EA(this));
3020
3189
  this.registerPlugin(new Label_44_ETA(this));
3021
3190
  this.registerPlugin(new Label_44_IN(this));