@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.mjs CHANGED
@@ -16,20 +16,22 @@ var IcaoDecoder = class {
16
16
  var DecoderPlugin = class {
17
17
  decoder;
18
18
  name = "unknown";
19
- defaultResult = {
20
- decoded: false,
21
- decoder: {
22
- name: "unknown",
23
- type: "pattern-match",
24
- decodeLevel: "none"
25
- },
26
- formatted: {
27
- description: "Unknown",
28
- items: []
29
- },
30
- raw: {},
31
- remaining: {}
32
- };
19
+ defaultResult() {
20
+ return {
21
+ decoded: false,
22
+ decoder: {
23
+ name: "unknown",
24
+ type: "pattern-match",
25
+ decodeLevel: "none"
26
+ },
27
+ formatted: {
28
+ description: "Unknown",
29
+ items: []
30
+ },
31
+ raw: {},
32
+ remaining: {}
33
+ };
34
+ }
33
35
  options;
34
36
  constructor(decoder, options = {}) {
35
37
  this.decoder = decoder;
@@ -52,7 +54,7 @@ var DecoderPlugin = class {
52
54
  };
53
55
  }
54
56
  decode(message) {
55
- const decodeResult = this.defaultResult;
57
+ const decodeResult = this.defaultResult();
56
58
  decodeResult.remaining.text = message.text;
57
59
  return decodeResult;
58
60
  }
@@ -92,7 +94,7 @@ var Label_5Z = class extends DecoderPlugin {
92
94
  };
93
95
  }
94
96
  decode(message, options = {}) {
95
- const decodeResult = this.defaultResult;
97
+ const decodeResult = this.defaultResult();
96
98
  decodeResult.decoder.name = this.name;
97
99
  decodeResult.formatted.description = "Airline Designated Downlink";
98
100
  const uaRegex = /^\/(?<type>\w+) (?<remainder>.+)/;
@@ -169,6 +171,12 @@ var Label_5Z = class extends DecoderPlugin {
169
171
 
170
172
  // lib/utils/coordinate_utils.ts
171
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
+ */
172
180
  static decodeStringCoordinates(stringCoords) {
173
181
  var results = {};
174
182
  const firstChar = stringCoords.substring(0, 1);
@@ -186,6 +194,33 @@ var CoordinateUtils = class {
186
194
  }
187
195
  return results;
188
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
+ }
189
224
  static coordinateString(coords) {
190
225
  const latDir = coords.latitude > 0 ? "N" : "S";
191
226
  const lonDir = coords.longitude > 0 ? "E" : "W";
@@ -203,7 +238,7 @@ var Label_12_N_Space = class extends DecoderPlugin {
203
238
  };
204
239
  }
205
240
  decode(message, options = {}) {
206
- const decodeResult = this.defaultResult;
241
+ const decodeResult = this.defaultResult();
207
242
  decodeResult.decoder.name = this.name;
208
243
  decodeResult.formatted.description = "Position Report";
209
244
  decodeResult.message = message;
@@ -256,7 +291,7 @@ var Label_15 = class extends DecoderPlugin {
256
291
  };
257
292
  }
258
293
  decode(message, options = {}) {
259
- const decodeResult = this.defaultResult;
294
+ const decodeResult = this.defaultResult();
260
295
  decodeResult.decoder.name = this.name;
261
296
  decodeResult.formatted.description = "Position Report";
262
297
  const twoZeeRegex = /^\(2(?<between>.+)\(Z$/;
@@ -288,7 +323,7 @@ var Label_15_FST = class extends DecoderPlugin {
288
323
  };
289
324
  }
290
325
  decode(message, options = {}) {
291
- const decodeResult = this.defaultResult;
326
+ const decodeResult = this.defaultResult();
292
327
  decodeResult.decoder.name = this.name;
293
328
  decodeResult.formatted.description = "Position Report";
294
329
  decodeResult.message = message;
@@ -339,7 +374,7 @@ var Label_16_N_Space = class extends DecoderPlugin {
339
374
  };
340
375
  }
341
376
  decode(message, options = {}) {
342
- const decodeResult = this.defaultResult;
377
+ const decodeResult = this.defaultResult();
343
378
  decodeResult.decoder.name = this.name;
344
379
  decodeResult.formatted.description = "Position Report";
345
380
  decodeResult.message = message;
@@ -462,7 +497,7 @@ var Label_1M_Slash = class extends DecoderPlugin {
462
497
  };
463
498
  }
464
499
  decode(message, options = {}) {
465
- const decodeResult = this.defaultResult;
500
+ const decodeResult = this.defaultResult();
466
501
  decodeResult.decoder.name = this.name;
467
502
  decodeResult.formatted.description = "ETA Report";
468
503
  decodeResult.message = message;
@@ -512,7 +547,7 @@ var Label_20_POS = class extends DecoderPlugin {
512
547
  };
513
548
  }
514
549
  decode(message, options = {}) {
515
- const decodeResult = this.defaultResult;
550
+ const decodeResult = this.defaultResult();
516
551
  decodeResult.decoder.name = this.name;
517
552
  decodeResult.formatted.description = "Position Report";
518
553
  decodeResult.message = message;
@@ -556,6 +591,96 @@ var Label_20_POS = class extends DecoderPlugin {
556
591
  }
557
592
  };
558
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
+
559
684
  // lib/plugins/Label_30_Slash_EA.ts
560
685
  var Label_30_Slash_EA = class extends DecoderPlugin {
561
686
  name = "label-30-slash-ea";
@@ -566,7 +691,7 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
566
691
  };
567
692
  }
568
693
  decode(message, options = {}) {
569
- const decodeResult = this.defaultResult;
694
+ const decodeResult = this.defaultResult();
570
695
  decodeResult.decoder.name = this.name;
571
696
  decodeResult.formatted.description = "ETA Report";
572
697
  decodeResult.message = message;
@@ -611,7 +736,7 @@ var Label_44_ETA = class extends DecoderPlugin {
611
736
  };
612
737
  }
613
738
  decode(message, options = {}) {
614
- const decodeResult = this.defaultResult;
739
+ const decodeResult = this.defaultResult();
615
740
  decodeResult.decoder.name = this.name;
616
741
  decodeResult.formatted.description = "ETA Report";
617
742
  decodeResult.message = message;
@@ -668,7 +793,7 @@ var Label_44_IN = class extends DecoderPlugin {
668
793
  };
669
794
  }
670
795
  decode(message, options = {}) {
671
- const decodeResult = this.defaultResult;
796
+ const decodeResult = this.defaultResult();
672
797
  decodeResult.decoder.name = this.name;
673
798
  decodeResult.formatted.description = "In Air Report";
674
799
  decodeResult.message = message;
@@ -725,7 +850,7 @@ var Label_44_OFF = class extends DecoderPlugin {
725
850
  };
726
851
  }
727
852
  decode(message, options = {}) {
728
- const decodeResult = this.defaultResult;
853
+ const decodeResult = this.defaultResult();
729
854
  decodeResult.decoder.name = this.name;
730
855
  decodeResult.formatted.description = "Off Runway Report";
731
856
  decodeResult.message = message;
@@ -785,7 +910,7 @@ var Label_44_ON = class extends DecoderPlugin {
785
910
  };
786
911
  }
787
912
  decode(message, options = {}) {
788
- const decodeResult = this.defaultResult;
913
+ const decodeResult = this.defaultResult();
789
914
  decodeResult.decoder.name = this.name;
790
915
  decodeResult.formatted.description = "On Runway Report";
791
916
  decodeResult.message = message;
@@ -842,7 +967,7 @@ var Label_44_POS = class extends DecoderPlugin {
842
967
  };
843
968
  }
844
969
  decode(message, options = {}) {
845
- const decodeResult = this.defaultResult;
970
+ const decodeResult = this.defaultResult();
846
971
  decodeResult.decoder.name = this.name;
847
972
  decodeResult.formatted.description = "Position Report";
848
973
  decodeResult.message = message;
@@ -853,7 +978,7 @@ var Label_44_POS = class extends DecoderPlugin {
853
978
  console.log(`Label 44 Position Report: groups`);
854
979
  console.log(results.groups);
855
980
  }
856
- decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
981
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
857
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);
858
983
  decodeResult.raw.departure_icao = results.groups.departure_icao;
859
984
  decodeResult.raw.arrival_icao = results.groups.arrival_icao;
@@ -868,9 +993,9 @@ var Label_44_POS = class extends DecoderPlugin {
868
993
  }
869
994
  if (decodeResult.raw.position) {
870
995
  decodeResult.formatted.items.push({
871
- type: "position",
996
+ type: "aircraft_position",
872
997
  code: "POS",
873
- label: "Position",
998
+ label: "Aircraft Position",
874
999
  value: CoordinateUtils.coordinateString(decodeResult.raw.position)
875
1000
  });
876
1001
  }
@@ -924,7 +1049,7 @@ var Label_80 = class extends DecoderPlugin {
924
1049
  };
925
1050
  }
926
1051
  decode(message, options = {}) {
927
- const decodeResult = this.defaultResult;
1052
+ const decodeResult = this.defaultResult();
928
1053
  decodeResult.decoder.name = this.name;
929
1054
  decodeResult.formatted.description = "Airline Defined Position Report";
930
1055
  const parts = message.text.split("\n");
@@ -1102,7 +1227,7 @@ var Label_8E = class extends DecoderPlugin {
1102
1227
  };
1103
1228
  }
1104
1229
  decode(message, options = {}) {
1105
- const decodeResult = this.defaultResult;
1230
+ const decodeResult = this.defaultResult();
1106
1231
  decodeResult.decoder.name = this.name;
1107
1232
  decodeResult.formatted.description = "ETA Report";
1108
1233
  decodeResult.message = message;
@@ -1143,7 +1268,7 @@ var Label_B6_Forwardslash = class extends DecoderPlugin {
1143
1268
  };
1144
1269
  }
1145
1270
  decode(message, options = {}) {
1146
- const decodeResult = this.defaultResult;
1271
+ const decodeResult = this.defaultResult();
1147
1272
  decodeResult.decoder.name = this.name;
1148
1273
  decodeResult.formatted.description = "CPDLC Message";
1149
1274
  decodeResult.message = message;
@@ -1163,7 +1288,7 @@ var Label_ColonComma = class extends DecoderPlugin {
1163
1288
  };
1164
1289
  }
1165
1290
  decode(message, options = {}) {
1166
- const decodeResult = this.defaultResult;
1291
+ const decodeResult = this.defaultResult();
1167
1292
  decodeResult.decoder.name = this.name;
1168
1293
  decodeResult.raw.frequency = Number(message.text) / 1e3;
1169
1294
  decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
@@ -1178,6 +1303,112 @@ var Label_ColonComma = class extends DecoderPlugin {
1178
1303
  }
1179
1304
  };
1180
1305
 
1306
+ // lib/utils/result_formatter.ts
1307
+ var ResultFormatter = class {
1308
+ static altitude(decodeResult, value) {
1309
+ decodeResult.raw.altitude = value;
1310
+ decodeResult.formatted.items.push({
1311
+ type: "altitude",
1312
+ code: "ALT",
1313
+ label: "Altitude",
1314
+ value: `${decodeResult.raw.altitude} feet`
1315
+ });
1316
+ }
1317
+ static flightNumber(decodeResult, value) {
1318
+ decodeResult.raw.flight_number = value;
1319
+ }
1320
+ static departureAirport(decodeResult, value) {
1321
+ decodeResult.raw.departure_icao = value;
1322
+ decodeResult.formatted.items.push({
1323
+ type: "origin",
1324
+ code: "ORG",
1325
+ label: "Origin",
1326
+ value: decodeResult.raw.departure_icao
1327
+ });
1328
+ }
1329
+ static departureRunway(decodeResult, value) {
1330
+ decodeResult.raw.departure_runway = value;
1331
+ decodeResult.formatted.items.push({
1332
+ type: "runway",
1333
+ code: "DEPRWY",
1334
+ label: "Departure Runway",
1335
+ value: decodeResult.raw.departure_runway
1336
+ });
1337
+ }
1338
+ static arrivalAirport(decodeResult, value) {
1339
+ decodeResult.raw.arrival_icao = value;
1340
+ decodeResult.formatted.items.push({
1341
+ type: "destination",
1342
+ code: "DST",
1343
+ label: "Destination",
1344
+ value: decodeResult.raw.arrival_icao
1345
+ });
1346
+ }
1347
+ static eta(decodeResult, value) {
1348
+ decodeResult.formatted.items.push({
1349
+ type: "eta",
1350
+ code: "ETA",
1351
+ label: "Estimated Time of Arrival",
1352
+ value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
1353
+ });
1354
+ }
1355
+ static arrivalRunway(decodeResult, value) {
1356
+ decodeResult.raw.arrival_runway = value;
1357
+ decodeResult.formatted.items.push({
1358
+ type: "runway",
1359
+ label: "Arrival Runway",
1360
+ value: decodeResult.raw.arrival_runway
1361
+ });
1362
+ }
1363
+ static currentFuel(decodeResult, value) {
1364
+ decodeResult.raw.fuel_on_board = value;
1365
+ decodeResult.formatted.items.push({
1366
+ type: "fuel_on_board",
1367
+ code: "FOB",
1368
+ label: "Fuel On Board",
1369
+ value: decodeResult.raw.fuel_on_board.toString()
1370
+ });
1371
+ }
1372
+ static remainingFuel(decodeResult, value) {
1373
+ decodeResult.raw.fuel_remaining = value;
1374
+ decodeResult.formatted.items.push({
1375
+ type: "fuel_remaining",
1376
+ label: "Fuel Remaining",
1377
+ value: decodeResult.raw.fuel_remaining.toString()
1378
+ });
1379
+ }
1380
+ static checksum(decodeResult, value) {
1381
+ decodeResult.raw.checksum = Number("0x" + value);
1382
+ decodeResult.formatted.items.push({
1383
+ type: "message_checksum",
1384
+ code: "CHECKSUM",
1385
+ label: "Message Checksum",
1386
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1387
+ });
1388
+ }
1389
+ static groundspeed(decodeResult, value) {
1390
+ decodeResult.raw.groundspeed = value;
1391
+ decodeResult.formatted.items.push({
1392
+ type: "aircraft_groundspeed",
1393
+ code: "GSPD",
1394
+ label: "Aircraft Groundspeed",
1395
+ value: `${decodeResult.raw.groundspeed}`
1396
+ });
1397
+ }
1398
+ static temperature(decodeResult, value) {
1399
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1400
+ decodeResult.formatted.items.push({
1401
+ type: "outside_air_temperature",
1402
+ code: "OATEMP",
1403
+ label: "Outside Air Temperature (C)",
1404
+ value: `${decodeResult.raw.outside_air_temperature}`
1405
+ });
1406
+ }
1407
+ static unknown(decodeResult, value) {
1408
+ decodeResult.remaining.text += "," + value;
1409
+ }
1410
+ };
1411
+
1181
1412
  // lib/utils/route_utils.ts
1182
1413
  var RouteUtils = class _RouteUtils {
1183
1414
  static routeToString(route) {
@@ -1218,13 +1449,13 @@ var RouteUtils = class _RouteUtils {
1218
1449
  }
1219
1450
  const waypoint = leg.split(",");
1220
1451
  if (waypoint.length == 2) {
1221
- const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1452
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
1222
1453
  if (position) {
1223
1454
  return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1224
1455
  }
1225
1456
  }
1226
1457
  if (leg.length == 13 || leg.length == 14) {
1227
- const position = CoordinateUtils.decodeStringCoordinates(leg);
1458
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
1228
1459
  const name = waypoint.length == 2 ? waypoint[0] : "";
1229
1460
  if (position) {
1230
1461
  return { name, latitude: position.latitude, longitude: position.longitude };
@@ -1250,7 +1481,7 @@ var RouteUtils = class _RouteUtils {
1250
1481
  };
1251
1482
 
1252
1483
  // lib/utils/flight_plan_utils.ts
1253
- var FlightPlanUtils = class {
1484
+ var FlightPlanUtils = class _FlightPlanUtils {
1254
1485
  /**
1255
1486
  * Processes flight plan data
1256
1487
  *
@@ -1261,7 +1492,7 @@ var FlightPlanUtils = class {
1261
1492
  * @returns whether all fields were processed or not
1262
1493
  */
1263
1494
  static processFlightPlan(decodeResult, data) {
1264
- let allKnownFields = parseHeader(decodeResult, data[0]);
1495
+ let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
1265
1496
  for (let i = 1; i < data.length; i += 2) {
1266
1497
  const key = data[i];
1267
1498
  const value = data[i + 1];
@@ -1301,60 +1532,9 @@ var FlightPlanUtils = class {
1301
1532
  }
1302
1533
  return allKnownFields;
1303
1534
  }
1304
- };
1305
- function parseMessageType(decodeResult, messageType) {
1306
- let decoded = true;
1307
- const parts = messageType.split("#");
1308
- if (parts.length == 1) {
1309
- if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1310
- decoded = processPosition(decodeResult, parts[0].substring(3));
1311
- }
1312
- return decoded;
1313
- } else if (parts.length == 2) {
1314
- if (parts[0].length > 0) {
1315
- decodeResult.remaining.text += parts[0].substring(0, 3);
1316
- decodeResult.raw.flight_number = parts[0].substring(3);
1317
- decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1318
- }
1319
- if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1320
- decoded = processPosition(decodeResult, parts[1].substring(6));
1321
- }
1322
- decodeResult.raw.message_type = messageType;
1323
- return decoded;
1324
- }
1325
- decodeResult.remaining.text += messageType;
1326
- return false;
1327
- }
1328
- function parseHeader(decodeResult, header) {
1329
- let allKnownFields = true;
1330
- const fields = header.split("/");
1331
- allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1332
- for (let i = 1; i < fields.length; ++i) {
1333
- if (fields[i].startsWith("FN")) {
1334
- decodeResult.raw.flight_number = fields[i].substring(2);
1335
- } else if (fields[i].startsWith("SN")) {
1336
- decodeResult.raw.serial_number = fields[i].substring(2);
1337
- } else if (fields[i].startsWith("TS")) {
1338
- const ts = fields[i].substring(2).split(",");
1339
- let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1340
- if (Number.isNaN(time)) {
1341
- const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1342
- time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1343
- }
1344
- decodeResult.raw.message_timestamp = time;
1345
- } else if (fields[i].startsWith("PS")) {
1346
- const pos = fields[i].substring(2);
1347
- allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1348
- } else if (fields[i].startsWith("DT")) {
1349
- const icao = fields[i].substring(2);
1350
- decodeResult.raw.arrival_icao = icao;
1351
- decodeResult.formatted.items.push({
1352
- type: "destination",
1353
- code: "DST",
1354
- label: "Destination",
1355
- value: decodeResult.raw.arrival_icao
1356
- });
1357
- } else if (fields[i].startsWith("RF")) {
1535
+ static parseHeader(decodeResult, header) {
1536
+ let allKnownFields = true;
1537
+ if (header.startsWith("RF")) {
1358
1538
  decodeResult.formatted.items.push({
1359
1539
  type: "status",
1360
1540
  code: "ROUTE_STATUS",
@@ -1362,10 +1542,10 @@ function parseHeader(decodeResult, header) {
1362
1542
  value: "Route Filed"
1363
1543
  });
1364
1544
  decodeResult.raw.route_status = "RF";
1365
- if (fields[i].length > 2) {
1366
- addRoute(decodeResult, fields[i].substring(2));
1545
+ if (header.length > 2) {
1546
+ addRoute(decodeResult, header.substring(2));
1367
1547
  }
1368
- } else if (fields[i] == "RP") {
1548
+ } else if (header.startsWith("RP")) {
1369
1549
  decodeResult.raw.route_status = "RP";
1370
1550
  decodeResult.formatted.items.push({
1371
1551
  type: "status",
@@ -1373,8 +1553,8 @@ function parseHeader(decodeResult, header) {
1373
1553
  label: "Route Status",
1374
1554
  value: "Route Planned"
1375
1555
  });
1376
- decodeResult.raw.route_status = fields[i];
1377
- } else if (fields[i] == "RI") {
1556
+ decodeResult.raw.route_status = header;
1557
+ } else if (header.startsWith("RI")) {
1378
1558
  decodeResult.raw.route_status = "RI";
1379
1559
  decodeResult.formatted.items.push({
1380
1560
  type: "status",
@@ -1383,58 +1563,23 @@ function parseHeader(decodeResult, header) {
1383
1563
  value: "Route Inactive"
1384
1564
  });
1385
1565
  } else {
1386
- decodeResult.remaining.text += "/" + fields[i];
1566
+ decodeResult.remaining.text += header;
1387
1567
  allKnownFields = false;
1388
1568
  }
1569
+ return allKnownFields;
1389
1570
  }
1390
- return allKnownFields;
1391
- }
1392
- function processPosition(decodeResult, value) {
1393
- const position = CoordinateUtils.decodeStringCoordinates(value);
1394
- if (position) {
1395
- decodeResult.raw.position = position;
1396
- decodeResult.formatted.items.push({
1397
- type: "aircraft_position",
1398
- code: "POS",
1399
- label: "Aircraft Position",
1400
- value: CoordinateUtils.coordinateString(position)
1401
- });
1402
- }
1403
- return !!position;
1404
- }
1571
+ };
1405
1572
  function addArrivalAirport(decodeResult, value) {
1406
- decodeResult.raw.arrival_icao = value;
1407
- decodeResult.formatted.items.push({
1408
- type: "destination",
1409
- code: "DST",
1410
- label: "Destination",
1411
- value: decodeResult.raw.arrival_icao
1412
- });
1573
+ ResultFormatter.arrivalAirport(decodeResult, value);
1413
1574
  }
1414
1575
  function addDepartureAirport(decodeResult, value) {
1415
- decodeResult.raw.departure_icao = value;
1416
- decodeResult.formatted.items.push({
1417
- type: "origin",
1418
- code: "ORG",
1419
- label: "Origin",
1420
- value: decodeResult.raw.departure_icao
1421
- });
1576
+ ResultFormatter.departureAirport(decodeResult, value);
1422
1577
  }
1423
1578
  function addRunway(decodeResult, value) {
1424
1579
  if (value.length === 8) {
1425
- decodeResult.raw.arrival_runway = value.substring(4, 7);
1426
- decodeResult.formatted.items.push({
1427
- type: "runway",
1428
- label: "Arrival Runway",
1429
- value: decodeResult.raw.arrival_runway
1430
- });
1580
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1431
1581
  }
1432
- decodeResult.raw.departure_runway = value.substring(0, 3);
1433
- decodeResult.formatted.items.push({
1434
- type: "runway",
1435
- label: "Departure Runway",
1436
- value: decodeResult.raw.departure_runway
1437
- });
1582
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1438
1583
  }
1439
1584
  function addRoute(decodeResult, value) {
1440
1585
  const route = value.split(".");
@@ -1494,6 +1639,241 @@ function addCompanyRoute(decodeResult, value) {
1494
1639
  });
1495
1640
  }
1496
1641
 
1642
+ // lib/utils/h1_helper.ts
1643
+ var H1Helper = class {
1644
+ static decodeH1Message(decodeResult, message) {
1645
+ let allKnownFields = true;
1646
+ const checksum = message.slice(-4);
1647
+ const data = message.slice(0, message.length - 4);
1648
+ const fields = data.split("/");
1649
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1650
+ for (let i = 1; i < fields.length; ++i) {
1651
+ if (fields[i].startsWith("FN")) {
1652
+ decodeResult.raw.flight_number = fields[i].substring(2);
1653
+ } else if (fields[i].startsWith("SN")) {
1654
+ decodeResult.raw.serial_number = fields[i].substring(2);
1655
+ } else if (fields[i].startsWith("DC")) {
1656
+ processDC(decodeResult, fields[i].substring(2).split(","));
1657
+ } else if (fields[i].startsWith("TS")) {
1658
+ const ts = fields[i].substring(2).split(",");
1659
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1660
+ if (Number.isNaN(time)) {
1661
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1662
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1663
+ }
1664
+ decodeResult.raw.message_date = ts[1];
1665
+ decodeResult.raw.message_timestamp = time;
1666
+ } else if (fields[i].startsWith("PS")) {
1667
+ const pos = processPS(decodeResult, fields[i].substring(2).split(","));
1668
+ allKnownFields == allKnownFields && pos;
1669
+ } else if (fields[i].startsWith("DT")) {
1670
+ const data2 = fields[i].substring(2).split(",");
1671
+ const dt = processDT(decodeResult, data2);
1672
+ allKnownFields = allKnownFields && dt;
1673
+ } else if (fields[i].startsWith("ID")) {
1674
+ const data2 = fields[i].substring(2).split(",");
1675
+ decodeResult.raw.tail = data2[0];
1676
+ decodeResult.formatted.items.push({
1677
+ type: "tail",
1678
+ code: "TAIL",
1679
+ label: "Tail",
1680
+ value: decodeResult.raw.tail
1681
+ });
1682
+ if (data2.length > 1) {
1683
+ decodeResult.raw.flight_number = data2[1];
1684
+ }
1685
+ if (data2.length > 2) {
1686
+ allKnownFields = false;
1687
+ decodeResult.remaining.text += "," + data2.slice(2).join(",");
1688
+ }
1689
+ } else if (fields[i].startsWith("LR")) {
1690
+ const data2 = fields[i].substring(2).split(",");
1691
+ const lr = processLR(decodeResult, data2);
1692
+ allKnownFields = allKnownFields && lr;
1693
+ } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1694
+ const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1695
+ allKnownFields = allKnownFields && fp;
1696
+ } else if (fields[i].startsWith("PR")) {
1697
+ allKnownFields = false;
1698
+ decodeResult.remaining.text += "/" + fields[i];
1699
+ } else if (fields[i].startsWith("PS")) {
1700
+ allKnownFields = false;
1701
+ decodeResult.remaining.text += fields[i];
1702
+ } else {
1703
+ decodeResult.remaining.text += "/" + fields[i];
1704
+ allKnownFields = false;
1705
+ }
1706
+ }
1707
+ if (decodeResult.formatted.items.length > 0) {
1708
+ ResultFormatter.checksum(decodeResult, checksum);
1709
+ }
1710
+ return allKnownFields;
1711
+ }
1712
+ };
1713
+ function processDT(decodeResult, data) {
1714
+ let allKnownFields = true;
1715
+ if (!decodeResult.raw.arrival_icao) {
1716
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
1717
+ } else if (decodeResult.raw.arrival_icao != data[0]) {
1718
+ decodeResult.remaining.text += "/" + data;
1719
+ }
1720
+ if (data.length > 1) {
1721
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
1722
+ }
1723
+ if (data.length > 2) {
1724
+ ResultFormatter.currentFuel(decodeResult, Number(data[2]));
1725
+ }
1726
+ if (data.length > 3) {
1727
+ ResultFormatter.eta(decodeResult, data[3]);
1728
+ }
1729
+ if (data.length > 4) {
1730
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
1731
+ }
1732
+ if (data.length > 5) {
1733
+ allKnownFields = false;
1734
+ decodeResult.remaining.text += "," + data.slice(5).join(",");
1735
+ }
1736
+ return allKnownFields;
1737
+ }
1738
+ function processLR(decodeResult, data) {
1739
+ let allKnownFields = true;
1740
+ if (data.length === 19) {
1741
+ ResultFormatter.unknown(decodeResult, data[1]);
1742
+ ResultFormatter.flightNumber(decodeResult, data[2]);
1743
+ ResultFormatter.departureAirport(decodeResult, data[3]);
1744
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
1745
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
1746
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
1747
+ allKnownFields = false;
1748
+ } else {
1749
+ allKnownFields = false;
1750
+ }
1751
+ return allKnownFields;
1752
+ }
1753
+ function parseMessageType(decodeResult, messageType) {
1754
+ let decoded = true;
1755
+ const parts = messageType.split("#");
1756
+ if (parts.length == 1) {
1757
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1758
+ decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
1759
+ }
1760
+ return decoded;
1761
+ } else if (parts.length == 2) {
1762
+ if (parts[0].length > 0) {
1763
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1764
+ decodeResult.raw.flight_number = parts[0].substring(3);
1765
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1766
+ }
1767
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1768
+ decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
1769
+ }
1770
+ decodeResult.raw.message_type = messageType;
1771
+ return decoded;
1772
+ }
1773
+ decodeResult.remaining.text += messageType;
1774
+ return false;
1775
+ }
1776
+ function processDC(decodeResult, data) {
1777
+ decodeResult.raw.message_date = data[0];
1778
+ if (data.length === 1) {
1779
+ } else if (data.length === 2) {
1780
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
1781
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
1782
+ decodeResult.raw.message_timestamp = time;
1783
+ } else {
1784
+ return false;
1785
+ }
1786
+ return true;
1787
+ }
1788
+ function processPS(decodeResult, data) {
1789
+ let allKnownFields = true;
1790
+ const position = CoordinateUtils.decodeStringCoordinates(data[0]);
1791
+ if (position) {
1792
+ decodeResult.raw.position = position;
1793
+ decodeResult.formatted.items.push({
1794
+ type: "aircraft_position",
1795
+ code: "POS",
1796
+ label: "Aircraft Position",
1797
+ value: CoordinateUtils.coordinateString(position)
1798
+ });
1799
+ } else {
1800
+ allKnownFields = false;
1801
+ }
1802
+ console.log("PS data.length: ", data.length);
1803
+ console.log("PS data: ", data);
1804
+ if (data.length === 9) {
1805
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
1806
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
1807
+ ResultFormatter.temperature(decodeResult, data[6]);
1808
+ ResultFormatter.unknown(decodeResult, data[7]);
1809
+ ResultFormatter.unknown(decodeResult, data[8]);
1810
+ }
1811
+ if (data.length === 14) {
1812
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1813
+ processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
1814
+ ResultFormatter.temperature(decodeResult, data[7]);
1815
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1816
+ ResultFormatter.unknown(decodeResult, data[1]);
1817
+ ResultFormatter.unknown(decodeResult, data[8]);
1818
+ ResultFormatter.unknown(decodeResult, data[9]);
1819
+ ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
1820
+ }
1821
+ allKnownFields = false;
1822
+ return allKnownFields;
1823
+ }
1824
+ function processPosition2(decodeResult, data) {
1825
+ let allKnownFields = true;
1826
+ const position = CoordinateUtils.decodeStringCoordinates(data[0]);
1827
+ if (position) {
1828
+ decodeResult.raw.position = position;
1829
+ decodeResult.formatted.items.push({
1830
+ type: "aircraft_position",
1831
+ code: "POS",
1832
+ label: "Aircraft Position",
1833
+ value: CoordinateUtils.coordinateString(position)
1834
+ });
1835
+ } else {
1836
+ allKnownFields = false;
1837
+ }
1838
+ console.log("data.length: ", data.length);
1839
+ console.log("data: ", data);
1840
+ if (data.length >= 10) {
1841
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1842
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1843
+ ResultFormatter.temperature(decodeResult, data[7]);
1844
+ ResultFormatter.unknown(decodeResult, data[8]);
1845
+ ResultFormatter.unknown(decodeResult, data[9]);
1846
+ }
1847
+ if (data.length >= 14) {
1848
+ ResultFormatter.groundspeed(decodeResult, Number(data[10]));
1849
+ ResultFormatter.unknown(decodeResult, data[11]);
1850
+ ResultFormatter.unknown(decodeResult, data[12]);
1851
+ ResultFormatter.unknown(decodeResult, data[13]);
1852
+ }
1853
+ allKnownFields = false;
1854
+ return allKnownFields;
1855
+ }
1856
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1857
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1858
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1859
+ const timeFormat = date ? "epoch" : "tod";
1860
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1861
+ lastWaypoint.time = lastTime;
1862
+ lastWaypoint.timeFormat = timeFormat;
1863
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1864
+ nextWaypoint.time = nextTime;
1865
+ nextWaypoint.timeFormat = timeFormat;
1866
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1867
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1868
+ decodeResult.raw.route = { waypoints };
1869
+ decodeResult.formatted.items.push({
1870
+ type: "aircraft_route",
1871
+ code: "ROUTE",
1872
+ label: "Aircraft Route",
1873
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1874
+ });
1875
+ }
1876
+
1497
1877
  // lib/plugins/Label_H1_FPN.ts
1498
1878
  var Label_H1_FPN = class extends DecoderPlugin {
1499
1879
  name = "label-h1-fpn";
@@ -1504,19 +1884,16 @@ var Label_H1_FPN = class extends DecoderPlugin {
1504
1884
  };
1505
1885
  }
1506
1886
  decode(message, options = {}) {
1507
- let decodeResult = this.defaultResult;
1887
+ let decodeResult = this.defaultResult();
1508
1888
  decodeResult.decoder.name = this.name;
1509
1889
  decodeResult.formatted.description = "Flight Plan";
1510
1890
  decodeResult.message = message;
1891
+ decodeResult.remaining.text = "";
1511
1892
  const msg = message.text.replace(/\n|\r/g, "");
1512
- const checksum = msg.slice(-4);
1513
- const data = msg.slice(0, msg.length - 4).split(":");
1514
- if (data.length > 1) {
1515
- const fulllyDecoded = FlightPlanUtils.processFlightPlan(decodeResult, data);
1516
- addChecksum(decodeResult, checksum);
1517
- decodeResult.decoded = true;
1518
- decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1519
- } else {
1893
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
1894
+ decodeResult.decoded = true;
1895
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1896
+ if (decodeResult.formatted.items.length === 0) {
1520
1897
  if (options?.debug) {
1521
1898
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1522
1899
  }
@@ -1527,15 +1904,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
1527
1904
  return decodeResult;
1528
1905
  }
1529
1906
  };
1530
- function addChecksum(decodeResult, value) {
1531
- decodeResult.raw.checksum = Number("0x" + value);
1532
- decodeResult.formatted.items.push({
1533
- type: "message_checksum",
1534
- code: "CHECKSUM",
1535
- label: "Message Checksum",
1536
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1537
- });
1538
- }
1539
1907
 
1540
1908
  // lib/plugins/Label_H1_OHMA.ts
1541
1909
  import * as zlib from "minizlib";
@@ -1548,7 +1916,7 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1548
1916
  };
1549
1917
  }
1550
1918
  decode(message, options = {}) {
1551
- let decodeResult = this.defaultResult;
1919
+ let decodeResult = this.defaultResult();
1552
1920
  decodeResult.decoder.name = this.name;
1553
1921
  decodeResult.formatted.description = "OHMA Message";
1554
1922
  decodeResult.message = message;
@@ -1561,13 +1929,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
1561
1929
  decompress.flush(zlib.constants.Z_SYNC_FLUSH);
1562
1930
  const result = decompress.read();
1563
1931
  const jsonText = result.toString();
1564
- const json = JSON.parse(jsonText);
1565
1932
  let formattedMsg;
1566
- if (json.message.startsWith("{")) {
1567
- const ohmaMsg = JSON.parse(json.message);
1933
+ let jsonMessage;
1934
+ try {
1935
+ jsonMessage = JSON.parse(jsonText).message;
1936
+ } catch {
1937
+ jsonMessage = jsonText;
1938
+ }
1939
+ try {
1940
+ const ohmaMsg = JSON.parse(jsonMessage);
1568
1941
  formattedMsg = JSON.stringify(ohmaMsg, null, 2);
1569
- } else {
1570
- formattedMsg = json.message;
1942
+ } catch {
1943
+ formattedMsg = jsonMessage;
1571
1944
  }
1572
1945
  decodeResult.decoded = true;
1573
1946
  decodeResult.decoder.decodeLevel = "full";
@@ -1595,236 +1968,31 @@ var Label_H1_POS = class extends DecoderPlugin {
1595
1968
  name = "label-h1-pos";
1596
1969
  qualifiers() {
1597
1970
  return {
1598
- labels: ["H1"],
1971
+ labels: ["H1", "4J"],
1599
1972
  preambles: ["POS", "#M1BPOS", "/.POS"]
1600
1973
  //TODO - support data before #
1601
1974
  };
1602
1975
  }
1603
1976
  decode(message, options = {}) {
1604
- let decodeResult = this.defaultResult;
1977
+ let decodeResult = this.defaultResult();
1605
1978
  decodeResult.decoder.name = this.name;
1606
1979
  decodeResult.formatted.description = "Position Report";
1607
1980
  decodeResult.message = message;
1608
1981
  decodeResult.remaining.text = "";
1609
- const checksum = message.text.slice(-4);
1610
- const header = findHeader(message.text.slice(0, -4));
1611
- const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1612
- const parts = message.text.replace(header, "").slice(0, -4).split(",");
1613
- if (parts.length == 1) {
1614
- if (decoded) {
1615
- processChecksum(decodeResult, checksum);
1616
- decodeResult.decoded = true;
1617
- decodeResult.decoder.decodeLevel = "full";
1618
- } else if (decodeResult.remaining.text.length > 0) {
1619
- processChecksum(decodeResult, checksum);
1620
- decodeResult.decoded = true;
1621
- decodeResult.decoder.decodeLevel = "partial";
1622
- } else {
1623
- decodeResult.decoded = false;
1624
- decodeResult.decoder.decodeLevel = "none";
1625
- }
1626
- } else if (parts.length === 10) {
1627
- processAlt(decodeResult, parts[3]);
1628
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1629
- processTemp(decodeResult, parts[7]);
1630
- processUnknown(decodeResult, parts[8]);
1631
- processUnknown(decodeResult, parts[9]);
1632
- processChecksum(decodeResult, checksum);
1633
- decodeResult.decoded = true;
1634
- decodeResult.decoder.decodeLevel = "partial";
1635
- } else if (parts.length === 11) {
1636
- processAlt(decodeResult, parts[3]);
1637
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1638
- processTemp(decodeResult, parts[7]);
1639
- processUnknown(decodeResult, parts[8]);
1640
- processUnknown(decodeResult, parts[9]);
1641
- processChecksum(decodeResult, checksum);
1642
- decodeResult.decoded = true;
1643
- decodeResult.decoder.decodeLevel = "partial";
1644
- } else if (parts.length === 12) {
1645
- const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1646
- processUnknown(decodeResult, parts[3]);
1647
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1648
- processTemp(decodeResult, parts[7]);
1649
- processUnknown(decodeResult, parts[8]);
1650
- processUnknown(decodeResult, parts[9]);
1651
- processUnknown(decodeResult, parts[10]);
1652
- processChecksum(decodeResult, checksum);
1653
- decodeResult.decoded = true;
1654
- decodeResult.decoder.decodeLevel = "partial";
1655
- } else if (parts.length === 14) {
1656
- processAlt(decodeResult, parts[3]);
1657
- processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1658
- processTemp(decodeResult, parts[7]);
1659
- processUnknown(decodeResult, parts[8]);
1660
- processUnknown(decodeResult, parts[9]);
1661
- processGndspd(decodeResult, parts[10]);
1662
- processUnknown(decodeResult, parts[11]);
1663
- processUnknown(decodeResult, parts[12]);
1664
- processUnknown(decodeResult, parts[13]);
1665
- processChecksum(decodeResult, checksum);
1666
- decodeResult.decoded = true;
1667
- decodeResult.decoder.decodeLevel = "partial";
1668
- } else if (parts.length === 15) {
1669
- processUnknown(decodeResult, parts[1]);
1670
- let date = void 0;
1671
- if (parts[2].startsWith("/DC")) {
1672
- date = parts[2].substring(3);
1673
- } else {
1674
- processUnknown(decodeResult, parts[2]);
1675
- }
1676
- processUnknown(decodeResult, parts[3]);
1677
- const fields = parts[4].split("/");
1678
- for (let i = 0; i < fields.length; ++i) {
1679
- const field = fields[i];
1680
- if (field.startsWith("PS")) {
1681
- processPosition2(decodeResult, field.substring(2));
1682
- } else {
1683
- if (i === 0) {
1684
- processUnknown(decodeResult, field);
1685
- } else {
1686
- processUnknown(decodeResult, "/" + field);
1687
- }
1688
- }
1689
- }
1690
- processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
1691
- processAlt(decodeResult, parts[6]);
1692
- processTemp(decodeResult, parts[10]);
1693
- processUnknown(decodeResult, parts[11]);
1694
- processUnknown(decodeResult, parts[12]);
1695
- processUnknown(decodeResult, parts[13]);
1696
- processUnknown(decodeResult, parts[14]);
1697
- processChecksum(decodeResult, checksum);
1698
- decodeResult.decoded = true;
1699
- decodeResult.decoder.decodeLevel = "partial";
1700
- } else if (parts.length === 21) {
1701
- processRunway(decodeResult, parts[1]);
1702
- processUnknown(decodeResult, parts.slice(2, 11).join(","));
1703
- processTemp(decodeResult, parts[11]);
1704
- processUnknown(decodeResult, parts.slice(12, 20).join(","));
1705
- FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1706
- processChecksum(decodeResult, checksum);
1707
- decodeResult.decoded = true;
1708
- decodeResult.decoder.decodeLevel = "partial";
1709
- } else if (parts.length === 32) {
1710
- processRunway(decodeResult, parts[1]);
1711
- const time = parts[2];
1712
- processUnknown(decodeResult, parts[3]);
1713
- const past = parts[4];
1714
- processUnknown(decodeResult, parts[5]);
1715
- const eta = parts[6];
1716
- const next = parts[7];
1717
- processUnknown(decodeResult, parts.slice(8, 14).join(","));
1718
- processUnknown(decodeResult, parts[16]);
1719
- processUnknown(decodeResult, parts[17]);
1720
- processUnknown(decodeResult, parts[18]);
1721
- processGndspd(decodeResult, parts[19]);
1722
- processUnknown(decodeResult, parts[20]);
1723
- processUnknown(decodeResult, parts[21]);
1724
- processAlt(decodeResult, parts[22]);
1725
- processUnknown(decodeResult, parts.slice(23, 31).join(","));
1726
- const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1727
- processRoute(decodeResult, past, time, next, eta);
1728
- decodeResult.decoded = true;
1729
- decodeResult.decoder.decodeLevel = "partial";
1730
- } else {
1731
- if (options.debug) {
1982
+ const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
1983
+ decodeResult.decoded = true;
1984
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1985
+ if (decodeResult.formatted.items.length === 0) {
1986
+ if (options?.debug) {
1732
1987
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1733
1988
  }
1734
- decodeResult.remaining.text += message.text;
1989
+ decodeResult.remaining.text = message.text;
1735
1990
  decodeResult.decoded = false;
1736
1991
  decodeResult.decoder.decodeLevel = "none";
1737
1992
  }
1738
1993
  return decodeResult;
1739
1994
  }
1740
1995
  };
1741
- function processUnknown(decodeResult, value) {
1742
- decodeResult.remaining.text += "," + value;
1743
- }
1744
- function processPosition2(decodeResult, value) {
1745
- const position = CoordinateUtils.decodeStringCoordinates(value);
1746
- if (position) {
1747
- decodeResult.raw.position = position;
1748
- decodeResult.formatted.items.push({
1749
- type: "aircraft_position",
1750
- code: "POS",
1751
- label: "Aircraft Position",
1752
- value: CoordinateUtils.coordinateString(position)
1753
- });
1754
- }
1755
- }
1756
- function processAlt(decodeResult, value) {
1757
- decodeResult.raw.altitude = Number(value) * 100;
1758
- decodeResult.formatted.items.push({
1759
- type: "altitude",
1760
- code: "ALT",
1761
- label: "Altitude",
1762
- value: `${decodeResult.raw.altitude} feet`
1763
- });
1764
- }
1765
- function processTemp(decodeResult, value) {
1766
- decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1767
- decodeResult.formatted.items.push({
1768
- type: "outside_air_temperature",
1769
- code: "OATEMP",
1770
- label: "Outside Air Temperature (C)",
1771
- value: `${decodeResult.raw.outside_air_temperature}`
1772
- });
1773
- }
1774
- function processRunway(decodeResult, value) {
1775
- decodeResult.raw.arrival_runway = value.replace("RW", "");
1776
- decodeResult.formatted.items.push({
1777
- type: "runway",
1778
- label: "Arrival Runway",
1779
- value: decodeResult.raw.arrival_runway
1780
- });
1781
- }
1782
- function processGndspd(decodeResult, value) {
1783
- decodeResult.raw.groundspeed = Number(value);
1784
- decodeResult.formatted.items.push({
1785
- type: "aircraft_groundspeed",
1786
- code: "GSPD",
1787
- label: "Aircraft Groundspeed",
1788
- value: `${decodeResult.raw.groundspeed}`
1789
- });
1790
- }
1791
- function processRoute(decodeResult, last, time, next, eta, then, date) {
1792
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1793
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1794
- const timeFormat = date ? "epoch" : "tod";
1795
- const lastWaypoint = RouteUtils.getWaypoint(last);
1796
- lastWaypoint.time = lastTime;
1797
- lastWaypoint.timeFormat = timeFormat;
1798
- const nextWaypoint = RouteUtils.getWaypoint(next);
1799
- nextWaypoint.time = nextTime;
1800
- nextWaypoint.timeFormat = timeFormat;
1801
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1802
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1803
- decodeResult.raw.route = { waypoints };
1804
- decodeResult.formatted.items.push({
1805
- type: "aircraft_route",
1806
- code: "ROUTE",
1807
- label: "Aircraft Route",
1808
- value: RouteUtils.routeToString(decodeResult.raw.route)
1809
- });
1810
- }
1811
- function processChecksum(decodeResult, value) {
1812
- decodeResult.raw.checksum = Number("0x" + value);
1813
- decodeResult.formatted.items.push({
1814
- type: "message_checksum",
1815
- code: "CHECKSUM",
1816
- label: "Message Checksum",
1817
- value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1818
- });
1819
- }
1820
- function findHeader(text) {
1821
- const parts = text.split(",");
1822
- const header = parts[0];
1823
- if (header.indexOf("/TS") === -1) {
1824
- return header;
1825
- }
1826
- return parts[0] + "," + parts[1];
1827
- }
1828
1996
 
1829
1997
  // lib/plugins/Label_H1_WRN.ts
1830
1998
  var Label_H1_WRN = class extends DecoderPlugin {
@@ -1836,7 +2004,7 @@ var Label_H1_WRN = class extends DecoderPlugin {
1836
2004
  };
1837
2005
  }
1838
2006
  decode(message, options = {}) {
1839
- let decodeResult = this.defaultResult;
2007
+ let decodeResult = this.defaultResult();
1840
2008
  decodeResult.decoder.name = this.name;
1841
2009
  decodeResult.formatted.description = "Warning Message";
1842
2010
  decodeResult.message = message;
@@ -1847,16 +2015,16 @@ var Label_H1_WRN = class extends DecoderPlugin {
1847
2015
  for (let i = 1; i < fields.length; i++) {
1848
2016
  const field = fields[i];
1849
2017
  if (field.startsWith("PN")) {
1850
- processUnknown2(decodeResult, "/" + field);
2018
+ processUnknown(decodeResult, "/" + field);
1851
2019
  } else {
1852
- processUnknown2(decodeResult, "/" + field);
2020
+ processUnknown(decodeResult, "/" + field);
1853
2021
  }
1854
2022
  }
1855
2023
  const data = parts[1].substring(0, 20);
1856
2024
  const msg = parts[1].substring(20);
1857
2025
  const datetime = data.substring(0, 12);
1858
2026
  const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
1859
- processUnknown2(decodeResult, data.substring(12));
2027
+ processUnknown(decodeResult, data.substring(12));
1860
2028
  decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
1861
2029
  decodeResult.raw.warning_message = msg;
1862
2030
  decodeResult.formatted.items.push({
@@ -1878,7 +2046,7 @@ var Label_H1_WRN = class extends DecoderPlugin {
1878
2046
  return decodeResult;
1879
2047
  }
1880
2048
  };
1881
- function processUnknown2(decodeResult, value) {
2049
+ function processUnknown(decodeResult, value) {
1882
2050
  decodeResult.remaining.text += value;
1883
2051
  }
1884
2052
 
@@ -1891,7 +2059,7 @@ var Label_SQ = class extends DecoderPlugin {
1891
2059
  };
1892
2060
  }
1893
2061
  decode(message, options = {}) {
1894
- const decodeResult = this.defaultResult;
2062
+ const decodeResult = this.defaultResult();
1895
2063
  decodeResult.decoder.name = this.name;
1896
2064
  decodeResult.raw.preamble = message.text.substring(0, 4);
1897
2065
  decodeResult.raw.version = message.text.substring(1, 2);
@@ -1990,7 +2158,7 @@ var Label_QR = class extends DecoderPlugin {
1990
2158
  };
1991
2159
  }
1992
2160
  decode(message, options = {}) {
1993
- const decodeResult = this.defaultResult;
2161
+ const decodeResult = this.defaultResult();
1994
2162
  decodeResult.decoder.name = this.name;
1995
2163
  decodeResult.raw.origin = message.text.substring(0, 4);
1996
2164
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2035,7 +2203,7 @@ var Label_QP = class extends DecoderPlugin {
2035
2203
  };
2036
2204
  }
2037
2205
  decode(message, options = {}) {
2038
- const decodeResult = this.defaultResult;
2206
+ const decodeResult = this.defaultResult();
2039
2207
  decodeResult.decoder.name = this.name;
2040
2208
  decodeResult.raw.origin = message.text.substring(0, 4);
2041
2209
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2080,7 +2248,7 @@ var Label_QS = class extends DecoderPlugin {
2080
2248
  };
2081
2249
  }
2082
2250
  decode(message, options = {}) {
2083
- const decodeResult = this.defaultResult;
2251
+ const decodeResult = this.defaultResult();
2084
2252
  decodeResult.decoder.name = this.name;
2085
2253
  decodeResult.raw.origin = message.text.substring(0, 4);
2086
2254
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2125,7 +2293,7 @@ var Label_QQ = class extends DecoderPlugin {
2125
2293
  };
2126
2294
  }
2127
2295
  decode(message, options = {}) {
2128
- const decodeResult = this.defaultResult;
2296
+ const decodeResult = this.defaultResult();
2129
2297
  decodeResult.decoder.name = this.name;
2130
2298
  decodeResult.raw.origin = message.text.substring(0, 4);
2131
2299
  decodeResult.raw.destination = message.text.substring(4, 8);
@@ -2979,6 +3147,7 @@ var MessageDecoder = class {
2979
3147
  this.registerPlugin(new Label_15_FST(this));
2980
3148
  this.registerPlugin(new Label_16_N_Space(this));
2981
3149
  this.registerPlugin(new Label_20_POS(this));
3150
+ this.registerPlugin(new Label_21_POS(this));
2982
3151
  this.registerPlugin(new Label_30_Slash_EA(this));
2983
3152
  this.registerPlugin(new Label_44_ETA(this));
2984
3153
  this.registerPlugin(new Label_44_IN(this));