@airframes/acars-decoder 1.6.18 → 1.6.19

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
@@ -28,12 +28,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // index.ts
31
- var acars_decoder_typescript_exports = {};
32
- __export(acars_decoder_typescript_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
33
  IcaoDecoder: () => IcaoDecoder,
34
34
  MessageDecoder: () => MessageDecoder
35
35
  });
36
- module.exports = __toCommonJS(acars_decoder_typescript_exports);
36
+ module.exports = __toCommonJS(index_exports);
37
37
 
38
38
  // lib/IcaoDecoder.ts
39
39
  var IcaoDecoder = class {
@@ -378,6 +378,9 @@ var ResultFormatter = class {
378
378
  });
379
379
  }
380
380
  static altitude(decodeResult, value) {
381
+ if (isNaN(value)) {
382
+ return;
383
+ }
381
384
  decodeResult.raw.altitude = value;
382
385
  decodeResult.formatted.items.push({
383
386
  type: "altitude",
@@ -1267,47 +1270,13 @@ var Label_16_N_Space = class extends DecoderPlugin {
1267
1270
  }
1268
1271
  };
1269
1272
 
1270
- // lib/plugins/Label_1M_Slash.ts
1271
- var Label_1M_Slash = class extends DecoderPlugin {
1272
- name = "label-1m-slash";
1273
- qualifiers() {
1274
- return {
1275
- labels: ["1M"],
1276
- preambles: ["/"]
1277
- };
1278
- }
1279
- decode(message, options = {}) {
1280
- const decodeResult = this.defaultResult();
1281
- decodeResult.decoder.name = this.name;
1282
- decodeResult.formatted.description = "ETA Report";
1283
- decodeResult.message = message;
1284
- const results = message.text.split(/\n|\//).slice(1);
1285
- if (results) {
1286
- if (options.debug) {
1287
- console.log(`Label 1M ETA: results`);
1288
- console.log(results);
1289
- }
1290
- decodeResult.raw.flight_number = results[0];
1291
- ResultFormatter.departureAirport(decodeResult, results[3]);
1292
- ResultFormatter.arrivalAirport(decodeResult, results[4]);
1293
- ResultFormatter.alternateAirport(decodeResult, results[5]);
1294
- ResultFormatter.arrivalRunway(decodeResult, results[8].replace(results[4], ""));
1295
- const yymmdd = results[2];
1296
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertDateTimeToEpoch(results[7] + "00", yymmdd.substring(2, 4) + yymmdd.substring(4, 6) + yymmdd.substring(0, 2)), "epoch");
1297
- }
1298
- decodeResult.decoded = true;
1299
- decodeResult.decoder.decodeLevel = "partial";
1300
- return decodeResult;
1301
- }
1302
- };
1303
-
1304
- // lib/plugins/Label_1L_3-line.ts
1305
- var Label_1L_3Line = class extends DecoderPlugin {
1306
- // eslint-disable-line camelcase
1307
- name = "label-1l-3-line";
1273
+ // lib/plugins/Label_16_POSA1.ts
1274
+ var Label_16_POSA1 = class extends DecoderPlugin {
1275
+ name = "label-16-posa1";
1308
1276
  qualifiers() {
1309
1277
  return {
1310
- labels: ["1L"]
1278
+ labels: ["16"],
1279
+ preambles: ["POSA1"]
1311
1280
  };
1312
1281
  }
1313
1282
  decode(message, options = {}) {
@@ -1315,88 +1284,39 @@ var Label_1L_3Line = class extends DecoderPlugin {
1315
1284
  decodeResult.decoder.name = this.name;
1316
1285
  decodeResult.formatted.description = "Position Report";
1317
1286
  decodeResult.message = message;
1318
- const lines = message.text.split("\r\n");
1319
- if (lines.length !== 3) {
1287
+ const fields = message.text.split(",");
1288
+ if (fields.length !== 11 || !fields[0].startsWith("POSA1")) {
1320
1289
  if (options.debug) {
1321
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1290
+ console.log(`Decoder: Unknown 16 message: ${message.text}`);
1322
1291
  }
1323
1292
  decodeResult.remaining.text = message.text;
1324
1293
  decodeResult.decoded = false;
1325
1294
  decodeResult.decoder.decodeLevel = "none";
1326
1295
  return decodeResult;
1327
1296
  }
1328
- const parts = message.text.replaceAll("\r\n", "/").split("/");
1329
- const data = /* @__PURE__ */ new Map();
1330
- data.set("", parts[0]);
1331
- for (let i = 1; i < parts.length; i++) {
1332
- const part = parts[i].split(" ");
1333
- data.set(part[0], part.slice(1).join(" "));
1334
- }
1335
- const dep = data.get("DEP");
1336
- if (dep) {
1337
- ResultFormatter.departureAirport(decodeResult, dep);
1338
- data.delete("DEP");
1339
- }
1340
- const des = data.get("DES");
1341
- if (des) {
1342
- ResultFormatter.arrivalAirport(decodeResult, des);
1343
- data.delete("DES");
1344
- }
1345
- const eta = data.get("ETA");
1346
- if (eta) {
1347
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
1348
- data.delete("ETA");
1349
- }
1350
- const alt = data.get("ALT");
1351
- if (alt) {
1352
- ResultFormatter.altitude(decodeResult, Number(alt));
1353
- data.delete("ALT");
1354
- }
1355
- const fn = data.get("FN");
1356
- if (fn) {
1357
- ResultFormatter.flightNumber(decodeResult, fn);
1358
- data.delete("FN");
1359
- }
1360
- const day = data.get("DAY");
1361
- const utc = data.get("UTC");
1362
- if (day && utc) {
1363
- decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
1364
- data.delete("DAY");
1365
- data.delete("UTC");
1366
- }
1367
- const lat = data.get("LAT");
1368
- const lon = data.get("LON");
1369
- if (lat && lon) {
1370
- ResultFormatter.position(decodeResult, {
1371
- latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
1372
- longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
1373
- });
1374
- data.delete("LAT");
1375
- data.delete("LON");
1376
- }
1377
- let remaining = "";
1378
- for (const [key, value] of data.entries()) {
1379
- if (key === "") {
1380
- remaining += value;
1381
- } else {
1382
- remaining += `/${key} ${value}`;
1383
- }
1384
- }
1385
- decodeResult.remaining.text = remaining;
1297
+ ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(fields[0].substring(5)));
1298
+ const waypoint = fields[1].trim();
1299
+ const time = DateTimeUtils.convertHHMMSSToTod(fields[2]);
1300
+ ResultFormatter.altitude(decodeResult, Number(fields[3]) * 100);
1301
+ const nextWaypoint = fields[4].trim();
1302
+ const nextTime = DateTimeUtils.convertHHMMSSToTod(fields[5]);
1303
+ ResultFormatter.unknownArr(decodeResult, fields.slice(6), ",");
1304
+ ResultFormatter.route(decodeResult, { waypoints: [
1305
+ { name: waypoint, time, timeFormat: "tod" },
1306
+ { name: nextWaypoint, time: nextTime, timeFormat: "tod" }
1307
+ ] });
1386
1308
  decodeResult.decoded = true;
1387
1309
  decodeResult.decoder.decodeLevel = "partial";
1388
1310
  return decodeResult;
1389
1311
  }
1390
1312
  };
1391
1313
 
1392
- // lib/plugins/Label_1L_070.ts
1393
- var Label_1L_070 = class extends DecoderPlugin {
1394
- // eslint-disable-line camelcase
1395
- name = "label-1l-070";
1314
+ // lib/plugins/Label_16_TOD.ts
1315
+ var Label_16_TOD = class extends DecoderPlugin {
1316
+ name = "label-16-tod";
1396
1317
  qualifiers() {
1397
1318
  return {
1398
- labels: ["1L"],
1399
- preambles: ["000000070"]
1319
+ labels: ["16"]
1400
1320
  };
1401
1321
  }
1402
1322
  decode(message, options = {}) {
@@ -1404,340 +1324,574 @@ var Label_1L_070 = class extends DecoderPlugin {
1404
1324
  decodeResult.decoder.name = this.name;
1405
1325
  decodeResult.formatted.description = "Position Report";
1406
1326
  decodeResult.message = message;
1407
- if (!message.text.startsWith("000000070")) {
1327
+ const fields = message.text.split(",");
1328
+ const time = DateTimeUtils.convertHHMMSSToTod(fields[0]);
1329
+ if (fields.length !== 5 || Number.isNaN(time)) {
1408
1330
  if (options.debug) {
1409
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1331
+ console.log(`Decoder: Unknown 16 message: ${message.text}`);
1410
1332
  }
1411
1333
  decodeResult.remaining.text = message.text;
1412
1334
  decodeResult.decoded = false;
1413
1335
  decodeResult.decoder.decodeLevel = "none";
1414
1336
  return decodeResult;
1415
1337
  }
1416
- const parts = message.text.substring(9).split(",");
1417
- if (parts.length !== 7) {
1418
- if (options.debug) {
1419
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1420
- }
1421
- decodeResult.remaining.text = message.text;
1422
- decodeResult.decoded = false;
1423
- decodeResult.decoder.decodeLevel = "none";
1424
- return decodeResult;
1338
+ ResultFormatter.time_of_day(decodeResult, time);
1339
+ if (fields[1] !== "") {
1340
+ ResultFormatter.altitude(decodeResult, Number(fields[1]));
1425
1341
  }
1426
- ResultFormatter.departureAirport(decodeResult, parts[0]);
1427
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
1428
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2]));
1429
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
1342
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
1343
+ ResultFormatter.unknown(decodeResult, fields[3]);
1344
+ const temp = fields[4].split("/");
1345
+ const posFields = temp[0].split(" ");
1430
1346
  ResultFormatter.position(decodeResult, {
1431
- latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
1432
- longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
1347
+ latitude: CoordinateUtils.getDirection(posFields[0]) * Number(posFields[1]),
1348
+ longitude: CoordinateUtils.getDirection(posFields[2]) * Number(posFields[3])
1433
1349
  });
1434
- decodeResult.remaining.text = parts[6];
1350
+ if (temp.length > 1) {
1351
+ ResultFormatter.flightNumber(decodeResult, temp[1]);
1352
+ }
1435
1353
  decodeResult.decoded = true;
1436
1354
  decodeResult.decoder.decodeLevel = "partial";
1437
1355
  return decodeResult;
1438
1356
  }
1439
1357
  };
1440
1358
 
1441
- // lib/plugins/Label_1L_660.ts
1442
- var Label_1L_660 = class extends DecoderPlugin {
1443
- // eslint-disable-line camelcase
1444
- name = "label-1l-660";
1445
- qualifiers() {
1446
- return {
1447
- labels: ["1L"],
1448
- preambles: ["000000660"]
1449
- };
1450
- }
1451
- decode(message, options = {}) {
1452
- const decodeResult = this.defaultResult();
1453
- decodeResult.decoder.name = this.name;
1454
- decodeResult.formatted.description = "Position Report";
1455
- decodeResult.message = message;
1456
- if (!message.text.startsWith("000000660")) {
1457
- if (options.debug) {
1458
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1359
+ // lib/utils/flight_plan_utils.ts
1360
+ var FlightPlanUtils = class _FlightPlanUtils {
1361
+ /**
1362
+ * Processes flight plan data
1363
+ *
1364
+ * Expected format is [header, key1, val1, ... keyN, valN]
1365
+ *
1366
+ * @param decodeResult - results
1367
+ * @param data - original message split by ':'
1368
+ * @returns whether all fields were processed or not
1369
+ */
1370
+ static processFlightPlan(decodeResult, data) {
1371
+ let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
1372
+ for (let i = 1; i < data.length; i += 2) {
1373
+ const key = data[i];
1374
+ const value = data[i + 1];
1375
+ switch (key) {
1376
+ case "A":
1377
+ addProcedure(decodeResult, value, "arrival");
1378
+ break;
1379
+ case "AA":
1380
+ addArrivalAirport(decodeResult, value);
1381
+ break;
1382
+ case "AP":
1383
+ addProcedure(decodeResult, value, "approach");
1384
+ break;
1385
+ case "CR":
1386
+ addCompanyRoute(decodeResult, value);
1387
+ break;
1388
+ case "D":
1389
+ addProcedure(decodeResult, value, "departure");
1390
+ break;
1391
+ case "DA":
1392
+ addDepartureAirport(decodeResult, value);
1393
+ break;
1394
+ case "F":
1395
+ addRoute(decodeResult, value);
1396
+ break;
1397
+ case "R":
1398
+ addRunway(decodeResult, value);
1399
+ break;
1400
+ // case 'WS': // something about routes, has altitude, so current parsing won't work
1401
+ // break;
1402
+ default:
1403
+ if (allKnownFields) {
1404
+ decodeResult.remaining.text = "";
1405
+ allKnownFields = false;
1406
+ }
1407
+ decodeResult.remaining.text += `:${key}:${value}`;
1408
+ decodeResult.decoder.decodeLevel = "partial";
1459
1409
  }
1460
- decodeResult.remaining.text = message.text;
1461
- decodeResult.decoded = false;
1462
- decodeResult.decoder.decodeLevel = "none";
1463
- return decodeResult;
1464
1410
  }
1465
- const parts = message.text.substring(9).split(",");
1466
- if (parts.length !== 5) {
1467
- if (options.debug) {
1468
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1411
+ return allKnownFields;
1412
+ }
1413
+ static parseHeader(decodeResult, header) {
1414
+ let allKnownFields = true;
1415
+ if (header.startsWith("RF")) {
1416
+ decodeResult.formatted.items.push({
1417
+ type: "status",
1418
+ code: "ROUTE_STATUS",
1419
+ label: "Route Status",
1420
+ value: "Route Filed"
1421
+ });
1422
+ decodeResult.raw.route_status = "RF";
1423
+ if (header.length > 2) {
1424
+ addRoute(decodeResult, header.substring(2));
1469
1425
  }
1470
- decodeResult.remaining.text = message.text;
1471
- decodeResult.decoded = false;
1472
- decodeResult.decoder.decodeLevel = "none";
1473
- return decodeResult;
1474
- }
1475
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(parts[0]);
1476
- if (position) {
1477
- ResultFormatter.position(decodeResult, position);
1426
+ } else if (header.startsWith("RP")) {
1427
+ decodeResult.raw.route_status = "RP";
1428
+ decodeResult.formatted.items.push({
1429
+ type: "status",
1430
+ code: "ROUTE_STATUS",
1431
+ label: "Route Status",
1432
+ value: "Route Planned"
1433
+ });
1434
+ decodeResult.raw.route_status = header;
1435
+ } else if (header.startsWith("RI")) {
1436
+ decodeResult.raw.route_status = "RI";
1437
+ decodeResult.formatted.items.push({
1438
+ type: "status",
1439
+ code: "ROUTE_STATUS",
1440
+ label: "Route Status",
1441
+ value: "Route Inactive"
1442
+ });
1443
+ } else {
1444
+ decodeResult.remaining.text += header;
1445
+ allKnownFields = false;
1478
1446
  }
1479
- const hhmmss = parts[1].substring(0, 6);
1480
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(hhmmss));
1481
- const fl = parts[1].substring(6, 9);
1482
- ResultFormatter.altitude(decodeResult, Number(fl) * 100);
1483
- const next = parts[1].substring(9);
1484
- ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
1485
- decodeResult.remaining.text = parts.slice(2).join(",");
1486
- decodeResult.decoded = true;
1487
- decodeResult.decoder.decodeLevel = "partial";
1488
- return decodeResult;
1447
+ return allKnownFields;
1489
1448
  }
1490
1449
  };
1491
-
1492
- // lib/plugins/Label_1L_Slash.ts
1493
- var Label_1L_Slash = class extends DecoderPlugin {
1494
- // eslint-disable-line camelcase
1495
- name = "label-1l-1-line";
1496
- qualifiers() {
1497
- return {
1498
- labels: ["1L"],
1499
- preambles: ["+", "-"]
1500
- };
1450
+ function addArrivalAirport(decodeResult, value) {
1451
+ ResultFormatter.arrivalAirport(decodeResult, value);
1452
+ }
1453
+ function addDepartureAirport(decodeResult, value) {
1454
+ ResultFormatter.departureAirport(decodeResult, value);
1455
+ }
1456
+ function addRunway(decodeResult, value) {
1457
+ if (value.length === 8) {
1458
+ ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
1501
1459
  }
1502
- decode(message, options = {}) {
1503
- const decodeResult = this.defaultResult();
1504
- decodeResult.decoder.name = this.name;
1505
- decodeResult.formatted.description = "Position Report";
1506
- decodeResult.message = message;
1507
- const parts = message.text.split("/");
1508
- if (parts.length !== 7) {
1509
- if (options.debug) {
1510
- console.log(`Decoder: Unknown 1L message: ${message.text}`);
1511
- }
1512
- decodeResult.remaining.text = message.text;
1460
+ ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
1461
+ }
1462
+ function addRoute(decodeResult, value) {
1463
+ const route = value.split(".");
1464
+ ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
1465
+ }
1466
+ function addProcedure(decodeResult, value, type) {
1467
+ if (decodeResult.raw.procedures === void 0) {
1468
+ decodeResult.raw.procedures = [];
1469
+ }
1470
+ const data = value.split(".");
1471
+ let waypoints;
1472
+ if (data.length > 1) {
1473
+ waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1474
+ }
1475
+ const route = { name: data[0], waypoints };
1476
+ decodeResult.raw.procedures.push({ type, route });
1477
+ const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
1478
+ let procedureValue = route.name;
1479
+ decodeResult.formatted.items.push({
1480
+ type: `procedure`,
1481
+ code: "proc",
1482
+ label: `${procedureName} Procedure`,
1483
+ value: RouteUtils.routeToString(route)
1484
+ });
1485
+ }
1486
+ function addCompanyRoute(decodeResult, value) {
1487
+ const segments = value.split(".");
1488
+ const parens_idx = segments[0].indexOf("(");
1489
+ let name;
1490
+ let runway;
1491
+ if (parens_idx === -1) {
1492
+ name = segments[0];
1493
+ } else {
1494
+ name = segments[0].slice(0, parens_idx);
1495
+ runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
1496
+ }
1497
+ let waypoints;
1498
+ if (segments.length > 1) {
1499
+ waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1500
+ }
1501
+ decodeResult.raw.company_route = {
1502
+ name,
1503
+ runway,
1504
+ waypoints
1505
+ };
1506
+ decodeResult.formatted.items.push({
1507
+ type: "company_route",
1508
+ code: "CR",
1509
+ label: "Company Route",
1510
+ value: RouteUtils.routeToString(decodeResult.raw.company_route)
1511
+ });
1512
+ }
1513
+
1514
+ // lib/utils/h1_helper.ts
1515
+ var H1Helper = class _H1Helper {
1516
+ static decodeH1Message(decodeResult, message) {
1517
+ const checksum = message.slice(-4);
1518
+ const data = message.slice(0, message.length - 4);
1519
+ const fields = data.split("/");
1520
+ const canDecode = parseMessageType(decodeResult, fields[0]);
1521
+ if (!canDecode) {
1513
1522
  decodeResult.decoded = false;
1514
1523
  decodeResult.decoder.decodeLevel = "none";
1515
- return decodeResult;
1524
+ return false;
1516
1525
  }
1517
- const data = /* @__PURE__ */ new Map();
1518
- data.set("LAT", parts[0].replaceAll(" ", ""));
1519
- data.set("LON", parts[1].replaceAll(" ", ""));
1520
- for (let i = 2; i < parts.length; i++) {
1521
- const part = parts[i].split(" ");
1522
- data.set(part[0], part.slice(1).join(" "));
1526
+ for (let i = 1; i < fields.length; ++i) {
1527
+ if (fields[i].startsWith("FN")) {
1528
+ decodeResult.raw.flight_number = fields[i].substring(2);
1529
+ } else if (fields[i].startsWith("SN")) {
1530
+ decodeResult.raw.serial_number = fields[i].substring(2);
1531
+ } else if (fields[i].startsWith("DC")) {
1532
+ processDC(decodeResult, fields[i].substring(2).split(","));
1533
+ } else if (fields[i].startsWith("TS")) {
1534
+ _H1Helper.processTS(decodeResult, fields[i].substring(2).split(","));
1535
+ } else if (fields[i].startsWith("PS")) {
1536
+ _H1Helper.processPS(decodeResult, fields[i].substring(2).split(","));
1537
+ } else if (fields[i].startsWith("DT")) {
1538
+ const data2 = fields[i].substring(2).split(",");
1539
+ processDT(decodeResult, data2);
1540
+ } else if (fields[i].startsWith("ID")) {
1541
+ processIdentification(decodeResult, fields[i].substring(2).split(","));
1542
+ } else if (fields[i].startsWith("LR")) {
1543
+ const data2 = fields[i].substring(2).split(",");
1544
+ processLR(decodeResult, data2);
1545
+ } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1546
+ FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1547
+ } else if (fields[i].startsWith("PR")) {
1548
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
1549
+ } else if (fields[i].startsWith("AF")) {
1550
+ processAirField(decodeResult, fields[i].substring(2).split(","));
1551
+ } else if (fields[i].startsWith("TD")) {
1552
+ processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
1553
+ } else if (fields[i].startsWith("FX")) {
1554
+ ResultFormatter.freetext(decodeResult, fields[i].substring(2));
1555
+ } else if (fields[i].startsWith("ET")) {
1556
+ if (fields[i].length === 7) {
1557
+ ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 3)));
1558
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3)));
1559
+ } else if (fields[i].length === 8) {
1560
+ ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 4)));
1561
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4)));
1562
+ } else {
1563
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
1564
+ }
1565
+ } else if (fields[i].startsWith("WD")) {
1566
+ processWindData(decodeResult, fields[i].substring(2));
1567
+ } else {
1568
+ ResultFormatter.unknown(decodeResult, fields[i], "/");
1569
+ }
1523
1570
  }
1524
- const position = {
1525
- latitude: Number(data.get("LAT")),
1526
- longitude: Number(data.get("LON"))
1527
- };
1528
- data.delete("LAT");
1529
- data.delete("LON");
1530
- ResultFormatter.position(decodeResult, position);
1531
- const utc = data.get("UTC");
1532
- if (utc) {
1533
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(utc));
1534
- data.delete("UTC");
1571
+ if (decodeResult.formatted.items.length > 0) {
1572
+ ResultFormatter.checksum(decodeResult, checksum);
1535
1573
  }
1536
- const alt = data.get("ALT");
1537
- if (alt) {
1538
- ResultFormatter.altitude(decodeResult, Number(alt));
1539
- data.delete("ALT");
1574
+ return true;
1575
+ }
1576
+ static processPS(decodeResult, data) {
1577
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1578
+ if (position) {
1579
+ decodeResult.raw.position = position;
1580
+ decodeResult.formatted.items.push({
1581
+ type: "aircraft_position",
1582
+ code: "POS",
1583
+ label: "Aircraft Position",
1584
+ value: CoordinateUtils.coordinateString(position)
1585
+ });
1540
1586
  }
1541
- const fob = data.get("FOB");
1542
- if (fob) {
1543
- ResultFormatter.currentFuel(decodeResult, Number(fob));
1544
- data.delete("FOB");
1587
+ if (data.length === 9) {
1588
+ processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
1589
+ ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
1590
+ ResultFormatter.temperature(decodeResult, data[6]);
1591
+ ResultFormatter.unknown(decodeResult, data[7]);
1592
+ ResultFormatter.unknown(decodeResult, data[8]);
1545
1593
  }
1546
- const eta = data.get("ETA");
1547
- if (eta) {
1548
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
1549
- data.delete("ETA");
1594
+ if (data.length === 14) {
1595
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1596
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1597
+ ResultFormatter.temperature(decodeResult, data[7]);
1598
+ ResultFormatter.unknownArr(decodeResult, data.slice(8));
1550
1599
  }
1551
- let remaining = "";
1552
- for (const [key, value] of data.entries()) {
1553
- remaining += `/${key} ${value}`;
1600
+ }
1601
+ static processPosition(decodeResult, data) {
1602
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
1603
+ if (position) {
1604
+ ResultFormatter.position(decodeResult, position);
1554
1605
  }
1555
- decodeResult.remaining.text = remaining;
1556
- decodeResult.decoded = true;
1557
- decodeResult.decoder.decodeLevel = "partial";
1558
- return decodeResult;
1606
+ if (data.length >= 10) {
1607
+ ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
1608
+ processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
1609
+ ResultFormatter.temperature(decodeResult, data[7]);
1610
+ ResultFormatter.unknown(decodeResult, data[8]);
1611
+ ResultFormatter.unknown(decodeResult, data[9]);
1612
+ }
1613
+ if (data.length >= 14) {
1614
+ ResultFormatter.unknownArr(decodeResult, data.slice(10));
1615
+ }
1616
+ }
1617
+ static processTS(decodeResult, data) {
1618
+ let time = DateTimeUtils.convertDateTimeToEpoch(data[0], data[1]);
1619
+ if (Number.isNaN(time)) {
1620
+ const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
1621
+ time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
1622
+ }
1623
+ decodeResult.raw.message_date = data[1];
1624
+ decodeResult.raw.message_timestamp = time;
1559
1625
  }
1560
1626
  };
1561
-
1562
- // lib/plugins/Label_20_POS.ts
1563
- var Label_20_POS = class extends DecoderPlugin {
1564
- name = "label-20-pos";
1565
- qualifiers() {
1566
- return {
1567
- labels: ["20"],
1568
- preambles: ["POS"]
1569
- };
1627
+ function processAirField(decodeResult, data) {
1628
+ if (data.length === 2) {
1629
+ ResultFormatter.departureAirport(decodeResult, data[0]);
1630
+ ResultFormatter.arrivalAirport(decodeResult, data[1]);
1631
+ } else {
1632
+ ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
1570
1633
  }
1571
- decode(message, options = {}) {
1572
- const decodeResult = this.defaultResult();
1573
- decodeResult.decoder.name = this.name;
1574
- decodeResult.formatted.description = "Position Report";
1575
- decodeResult.message = message;
1576
- decodeResult.raw.preamble = message.text.substring(0, 3);
1577
- const content = message.text.substring(3);
1578
- const fields = content.split(",");
1579
- if (fields.length == 11) {
1580
- if (options.debug) {
1581
- console.log(`DEBUG: ${this.name}: Variation 1 detected`);
1582
- }
1583
- const rawCoords = fields[0];
1584
- ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(rawCoords));
1585
- decodeResult.decoded = true;
1586
- decodeResult.decoder.decodeLevel = "full";
1587
- } else if (fields.length == 5) {
1588
- if (options.debug) {
1589
- console.log(`DEBUG: ${this.name}: Variation 2 detected`);
1590
- }
1591
- const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
1592
- if (position) {
1593
- ResultFormatter.position(decodeResult, position);
1594
- }
1595
- decodeResult.decoded = true;
1596
- decodeResult.decoder.decodeLevel = "full";
1597
- } else {
1598
- if (options.debug) {
1599
- console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
1634
+ }
1635
+ function processTimeOfDeparture(decodeResult, data) {
1636
+ if (data.length === 2) {
1637
+ decodeResult.raw.plannedDepartureTime = data[0];
1638
+ decodeResult.formatted.items.push({
1639
+ type: "ptd",
1640
+ code: "ptd",
1641
+ label: "Planned Departure Time",
1642
+ value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
1643
+ });
1644
+ decodeResult.raw.plannedDepartureTime = data[1];
1645
+ decodeResult.formatted.items.push({
1646
+ type: "etd",
1647
+ code: "etd",
1648
+ label: "Estimated Departure Time",
1649
+ value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
1650
+ });
1651
+ } else {
1652
+ ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
1653
+ }
1654
+ }
1655
+ function processIdentification(decodeResult, data) {
1656
+ ResultFormatter.tail(decodeResult, data[0]);
1657
+ if (data.length > 1) {
1658
+ ResultFormatter.flightNumber(decodeResult, data[1]);
1659
+ }
1660
+ if (data.length > 2) {
1661
+ decodeResult.raw.mission_number = data[2];
1662
+ }
1663
+ }
1664
+ function processDT(decodeResult, data) {
1665
+ if (!decodeResult.raw.arrival_icao) {
1666
+ ResultFormatter.arrivalAirport(decodeResult, data[0]);
1667
+ } else if (decodeResult.raw.arrival_icao != data[0]) {
1668
+ ResultFormatter.unknownArr(decodeResult, data);
1669
+ }
1670
+ if (data.length > 1) {
1671
+ ResultFormatter.arrivalRunway(decodeResult, data[1]);
1672
+ }
1673
+ if (data.length > 2) {
1674
+ ResultFormatter.currentFuel(decodeResult, Number(data[2]));
1675
+ }
1676
+ if (data.length > 3) {
1677
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
1678
+ }
1679
+ if (data.length > 4) {
1680
+ ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
1681
+ }
1682
+ if (data.length > 5) {
1683
+ ResultFormatter.unknownArr(decodeResult, data);
1684
+ }
1685
+ }
1686
+ function processLR(decodeResult, data) {
1687
+ if (data.length === 19) {
1688
+ ResultFormatter.unknown(decodeResult, data[1]);
1689
+ ResultFormatter.flightNumber(decodeResult, data[2]);
1690
+ ResultFormatter.departureAirport(decodeResult, data[3]);
1691
+ ResultFormatter.arrivalAirport(decodeResult, data[4]);
1692
+ ResultFormatter.arrivalRunway(decodeResult, data[5]);
1693
+ ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
1694
+ } else {
1695
+ ResultFormatter.unknown(decodeResult, data.join(","));
1696
+ }
1697
+ }
1698
+ function parseMessageType(decodeResult, messageType) {
1699
+ const parts = messageType.split("#");
1700
+ if (parts.length == 1) {
1701
+ if (parts[0].startsWith("POS")) {
1702
+ H1Helper.processPosition(decodeResult, parts[0].substring(3).split(","));
1703
+ return processMessageType(decodeResult, "POS");
1704
+ } else if (parts[0].length === 13) {
1705
+ if (processMessageType(decodeResult, parts[0].substring(10))) {
1706
+ ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
1707
+ ResultFormatter.flightNumber(decodeResult, parts[0].slice(4, 10));
1708
+ return true;
1600
1709
  }
1601
- decodeResult.decoded = false;
1602
- decodeResult.decoder.decodeLevel = "none";
1603
1710
  }
1604
- return decodeResult;
1711
+ return processMessageType(decodeResult, parts[0].substring(0, 3));
1712
+ } else if (parts.length == 2) {
1713
+ if (parts[0].length > 0) {
1714
+ ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
1715
+ ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
1716
+ ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
1717
+ }
1718
+ const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
1719
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
1720
+ H1Helper.processPosition(decodeResult, parts[1].substring(6).split(","));
1721
+ }
1722
+ return processMessageType(decodeResult, type);
1723
+ } else {
1724
+ ResultFormatter.unknown(decodeResult, messageType);
1725
+ return false;
1605
1726
  }
1606
- };
1727
+ }
1728
+ function processMessageType(decodeResult, type) {
1729
+ if (type === "FPN") {
1730
+ decodeResult.formatted.description = "Flight Plan";
1731
+ } else if (type === "FTX") {
1732
+ decodeResult.formatted.description = "Free Text";
1733
+ } else if (type === "INI") {
1734
+ decodeResult.formatted.description = "Flight Plan Initial Report";
1735
+ } else if (type === "POS") {
1736
+ decodeResult.formatted.description = "Position Report";
1737
+ } else if (type === "PRG") {
1738
+ decodeResult.formatted.description = "Progress Report";
1739
+ } else if (type === "PWI") {
1740
+ decodeResult.formatted.description = "Weather Report";
1741
+ } else {
1742
+ decodeResult.formatted.description = "Unknown H1 Message";
1743
+ return false;
1744
+ }
1745
+ return true;
1746
+ }
1747
+ function processDC(decodeResult, data) {
1748
+ decodeResult.raw.message_date = data[0];
1749
+ if (data.length === 1) {
1750
+ } else if (data.length === 2) {
1751
+ const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
1752
+ const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
1753
+ decodeResult.raw.message_timestamp = time;
1754
+ }
1755
+ }
1756
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1757
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1758
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1759
+ const timeFormat = date ? "epoch" : "tod";
1760
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1761
+ lastWaypoint.time = lastTime;
1762
+ lastWaypoint.timeFormat = timeFormat;
1763
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1764
+ nextWaypoint.time = nextTime;
1765
+ nextWaypoint.timeFormat = timeFormat;
1766
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1767
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1768
+ decodeResult.raw.route = { waypoints };
1769
+ decodeResult.formatted.items.push({
1770
+ type: "aircraft_route",
1771
+ code: "ROUTE",
1772
+ label: "Aircraft Route",
1773
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1774
+ });
1775
+ }
1776
+ function processWindData(decodeResult, message) {
1777
+ if (decodeResult.raw.wind_data === void 0) {
1778
+ decodeResult.raw.wind_data = [];
1779
+ }
1780
+ const flightLevel = Number(message.slice(0, 3));
1781
+ const fields = message.slice(4).split(".");
1782
+ fields.forEach((field) => {
1783
+ const data = field.split(",");
1784
+ const waypoint = data[0];
1785
+ const windData = data[1];
1786
+ const windDirection = Number(windData.slice(0, 3));
1787
+ const windSpeed = Number(windData.slice(3));
1788
+ if (data.length === 3) {
1789
+ const tempData = data[2];
1790
+ const tempFlightLevel = Number(tempData.slice(0, 3));
1791
+ const tempString = tempData.slice(3);
1792
+ const tempDegrees = Number(tempString.substring(1)) * (tempString.charAt(0) === "M" ? -1 : 1);
1793
+ decodeResult.raw.wind_data.push({
1794
+ waypoint,
1795
+ flightLevel,
1796
+ windDirection,
1797
+ windSpeed,
1798
+ temperature: {
1799
+ flightLevel: tempFlightLevel,
1800
+ degreesC: tempDegrees
1801
+ }
1802
+ });
1803
+ decodeResult.formatted.items.push({
1804
+ type: "wind_data",
1805
+ code: "WIND",
1806
+ label: "Wind Data",
1807
+ value: `${waypoint} at FL${flightLevel}: ${windDirection}\xB0 at ${windSpeed}kt, ${tempDegrees}\xB0C at FL${tempFlightLevel}`
1808
+ });
1809
+ } else {
1810
+ decodeResult.raw.wind_data.push({
1811
+ waypoint,
1812
+ flightLevel,
1813
+ windDirection,
1814
+ windSpeed
1815
+ });
1816
+ decodeResult.formatted.items.push({
1817
+ type: "wind_data",
1818
+ code: "WIND",
1819
+ label: "Wind Data",
1820
+ value: `${waypoint} at FL${flightLevel}: ${windDirection}\xB0 at ${windSpeed}kt`
1821
+ });
1822
+ }
1823
+ });
1824
+ }
1607
1825
 
1608
- // lib/plugins/Label_21_POS.ts
1609
- var Label_21_POS = class extends DecoderPlugin {
1610
- name = "label-21-pos";
1826
+ // lib/plugins/Label_1J_2J_FTX.ts
1827
+ var Label_1J_2J_FTX = class extends DecoderPlugin {
1828
+ name = "label-1j-2j-ftx";
1611
1829
  qualifiers() {
1612
1830
  return {
1613
- labels: ["21"],
1614
- preambles: ["POS"]
1831
+ labels: ["1J", "2J"]
1615
1832
  };
1616
1833
  }
1617
1834
  decode(message, options = {}) {
1618
- const decodeResult = this.defaultResult();
1835
+ let decodeResult = this.defaultResult();
1619
1836
  decodeResult.decoder.name = this.name;
1620
- decodeResult.formatted.description = "Position Report";
1621
1837
  decodeResult.message = message;
1622
- decodeResult.raw.preamble = message.text.substring(0, 3);
1623
- const content = message.text.substring(3);
1624
- const fields = content.split(",");
1625
- if (fields.length == 9) {
1626
- processPosition(decodeResult, fields[0].trim());
1627
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
1628
- ResultFormatter.altitude(decodeResult, Number(fields[3]));
1629
- ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
1630
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[7]));
1631
- ResultFormatter.arrivalAirport(decodeResult, fields[8]);
1632
- ResultFormatter.unknownArr(decodeResult, [fields[1], fields[4], fields[5]]);
1633
- decodeResult.decoded = true;
1634
- decodeResult.decoder.decodeLevel = "partial";
1635
- } else {
1838
+ const msg = message.text.replace(/\n|\r/g, "");
1839
+ const decoded = H1Helper.decodeH1Message(decodeResult, msg);
1840
+ decodeResult.decoded = decoded;
1841
+ decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
1842
+ if (decodeResult.formatted.items.length === 0) {
1636
1843
  if (options.debug) {
1637
- console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
1844
+ console.log(`Decoder: Unknown 1J/2J message: ${message.text}`);
1638
1845
  }
1846
+ ResultFormatter.unknown(decodeResult, message.text);
1639
1847
  decodeResult.decoded = false;
1640
1848
  decodeResult.decoder.decodeLevel = "none";
1641
1849
  }
1642
1850
  return decodeResult;
1643
1851
  }
1644
1852
  };
1645
- function processPosition(decodeResult, value) {
1646
- if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
1647
- return;
1648
- }
1649
- const latDir = value[0] === "N" ? 1 : -1;
1650
- const lonDir = value[8] === "E" ? 1 : -1;
1651
- const position = {
1652
- latitude: latDir * Number(value.substring(1, 7)),
1653
- longitude: lonDir * Number(value.substring(9, 15))
1654
- };
1655
- ResultFormatter.position(decodeResult, position);
1656
- }
1657
1853
 
1658
- // lib/plugins/Label_22_OFF.ts
1659
- var Label_22_OFF = class extends DecoderPlugin {
1660
- name = "label-22-off";
1854
+ // lib/plugins/Label_1M_Slash.ts
1855
+ var Label_1M_Slash = class extends DecoderPlugin {
1856
+ name = "label-1m-slash";
1661
1857
  qualifiers() {
1662
1858
  return {
1663
- labels: ["22"],
1664
- preambles: ["OFF"]
1859
+ labels: ["1M"],
1860
+ preambles: ["/"]
1665
1861
  };
1666
1862
  }
1667
1863
  decode(message, options = {}) {
1668
1864
  const decodeResult = this.defaultResult();
1669
1865
  decodeResult.decoder.name = this.name;
1670
- decodeResult.formatted.description = "Takeoff Report";
1866
+ decodeResult.formatted.description = "ETA Report";
1671
1867
  decodeResult.message = message;
1672
- if (message.text.startsWith("OFF01")) {
1673
- const fields = message.text.substring(5).split("/");
1674
- if (fields.length != 2) {
1675
- decodeResult.decoded = false;
1676
- decodeResult.decoder.decodeLevel = "none";
1677
- return decodeResult;
1678
- }
1679
- ResultFormatter.flightNumber(decodeResult, fields[0]);
1680
- ResultFormatter.departureDay(decodeResult, Number(fields[1].substring(0, 2)));
1681
- ResultFormatter.arrivalDay(decodeResult, Number(fields[1].substring(2, 4)));
1682
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8)));
1683
- ResultFormatter.departureAirport(decodeResult, fields[1].substring(8, 12));
1684
- ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
1685
- ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22)));
1686
- ResultFormatter.unknown(decodeResult, fields[1].substring(22));
1687
- decodeResult.decoded = true;
1688
- decodeResult.decoder.decodeLevel = "partial";
1689
- } else if (message.text.startsWith("OFF02\r\n")) {
1690
- const fields = message.text.substring(7).split(",");
1691
- if (fields.length != 4) {
1692
- decodeResult.decoded = false;
1693
- decodeResult.decoder.decodeLevel = "none";
1694
- return decodeResult;
1695
- }
1696
- ResultFormatter.departureAirport(decodeResult, fields[0]);
1697
- ResultFormatter.arrivalAirport(decodeResult, fields[1]);
1698
- ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
1699
- ResultFormatter.unknown(decodeResult, fields[3]);
1700
- decodeResult.decoded = true;
1701
- decodeResult.decoder.decodeLevel = "partial";
1702
- } else if (message.text.startsWith("OFF02")) {
1703
- const fields = message.text.substring(5).split("/");
1704
- if (fields.length != 2) {
1705
- decodeResult.decoded = false;
1706
- decodeResult.decoder.decodeLevel = "none";
1707
- return decodeResult;
1708
- }
1709
- ResultFormatter.flightNumber(decodeResult, fields[0]);
1710
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(fields[1].substring(0, 14));
1711
- if (position) {
1712
- ResultFormatter.position(decodeResult, position);
1713
- }
1714
- ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
1715
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20)));
1716
- ResultFormatter.departureAirport(decodeResult, fields[1].substring(20, 24));
1717
- ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
1718
- ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32)));
1719
- ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
1720
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40)));
1721
- decodeResult.decoded = true;
1722
- decodeResult.decoder.decodeLevel = "partial";
1723
- } else {
1868
+ const results = message.text.split(/\n|\//).slice(1);
1869
+ if (results) {
1724
1870
  if (options.debug) {
1725
- console.log(`DEBUG: ${this.name}: Unknown variation.`);
1871
+ console.log(`Label 1M ETA: results`);
1872
+ console.log(results);
1726
1873
  }
1727
- decodeResult.decoded = false;
1728
- decodeResult.decoder.decodeLevel = "none";
1874
+ decodeResult.raw.flight_number = results[0];
1875
+ ResultFormatter.departureAirport(decodeResult, results[3]);
1876
+ ResultFormatter.arrivalAirport(decodeResult, results[4]);
1877
+ ResultFormatter.alternateAirport(decodeResult, results[5]);
1878
+ ResultFormatter.arrivalRunway(decodeResult, results[8].replace(results[4], ""));
1879
+ const yymmdd = results[2];
1880
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertDateTimeToEpoch(results[7] + "00", yymmdd.substring(2, 4) + yymmdd.substring(4, 6) + yymmdd.substring(0, 2)), "epoch");
1729
1881
  }
1882
+ decodeResult.decoded = true;
1883
+ decodeResult.decoder.decodeLevel = "partial";
1730
1884
  return decodeResult;
1731
1885
  }
1732
1886
  };
1733
1887
 
1734
- // lib/plugins/Label_22_POS.ts
1735
- var Label_22_POS = class extends DecoderPlugin {
1736
- name = "label-22-pos";
1888
+ // lib/plugins/Label_1L_3-line.ts
1889
+ var Label_1L_3Line = class extends DecoderPlugin {
1890
+ // eslint-disable-line camelcase
1891
+ name = "label-1l-3-line";
1737
1892
  qualifiers() {
1738
1893
  return {
1739
- labels: ["22"],
1740
- preambles: ["N", "S"]
1894
+ labels: ["1L"]
1741
1895
  };
1742
1896
  }
1743
1897
  decode(message, options = {}) {
@@ -1745,653 +1899,618 @@ var Label_22_POS = class extends DecoderPlugin {
1745
1899
  decodeResult.decoder.name = this.name;
1746
1900
  decodeResult.formatted.description = "Position Report";
1747
1901
  decodeResult.message = message;
1748
- const fields = message.text.split(",");
1749
- if (fields.length !== 11) {
1902
+ const lines = message.text.split("\r\n");
1903
+ if (lines.length !== 3) {
1750
1904
  if (options.debug) {
1751
- console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`);
1905
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1752
1906
  }
1907
+ decodeResult.remaining.text = message.text;
1753
1908
  decodeResult.decoded = false;
1754
1909
  decodeResult.decoder.decodeLevel = "none";
1755
1910
  return decodeResult;
1756
1911
  }
1757
- const latStr = fields[0].substring(1, 8);
1758
- const lonStr = fields[0].substring(9);
1759
- const lat = Number(latStr) / 1e4;
1760
- const lon = Number(lonStr) / 1e4;
1761
- ResultFormatter.position(decodeResult, {
1762
- latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
1763
- longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
1764
- });
1765
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
1766
- ResultFormatter.altitude(decodeResult, Number(fields[3]));
1767
- ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
1912
+ const parts = message.text.replaceAll("\r\n", "/").split("/");
1913
+ const data = /* @__PURE__ */ new Map();
1914
+ data.set("", parts[0]);
1915
+ for (let i = 1; i < parts.length; i++) {
1916
+ const part = parts[i].split(" ");
1917
+ data.set(part[0], part.slice(1).join(" "));
1918
+ }
1919
+ const dep = data.get("DEP");
1920
+ if (dep) {
1921
+ ResultFormatter.departureAirport(decodeResult, dep);
1922
+ data.delete("DEP");
1923
+ }
1924
+ const des = data.get("DES");
1925
+ if (des) {
1926
+ ResultFormatter.arrivalAirport(decodeResult, des);
1927
+ data.delete("DES");
1928
+ }
1929
+ const eta = data.get("ETA");
1930
+ if (eta) {
1931
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
1932
+ data.delete("ETA");
1933
+ }
1934
+ const alt = data.get("ALT");
1935
+ if (alt) {
1936
+ ResultFormatter.altitude(decodeResult, Number(alt));
1937
+ data.delete("ALT");
1938
+ }
1939
+ const fn = data.get("FN");
1940
+ if (fn) {
1941
+ ResultFormatter.flightNumber(decodeResult, fn);
1942
+ data.delete("FN");
1943
+ }
1944
+ const day = data.get("DAY");
1945
+ const utc = data.get("UTC");
1946
+ if (day && utc) {
1947
+ decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
1948
+ data.delete("DAY");
1949
+ data.delete("UTC");
1950
+ }
1951
+ const lat = data.get("LAT");
1952
+ const lon = data.get("LON");
1953
+ if (lat && lon) {
1954
+ ResultFormatter.position(decodeResult, {
1955
+ latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
1956
+ longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
1957
+ });
1958
+ data.delete("LAT");
1959
+ data.delete("LON");
1960
+ }
1961
+ let remaining = "";
1962
+ for (const [key, value] of data.entries()) {
1963
+ if (key === "") {
1964
+ remaining += value;
1965
+ } else {
1966
+ remaining += `/${key} ${value}`;
1967
+ }
1968
+ }
1969
+ decodeResult.remaining.text = remaining;
1768
1970
  decodeResult.decoded = true;
1769
1971
  decodeResult.decoder.decodeLevel = "partial";
1770
1972
  return decodeResult;
1771
1973
  }
1772
1974
  };
1773
1975
 
1774
- // lib/plugins/Label_2P_FM3.ts
1775
- var Label_2P_FM3 = class extends DecoderPlugin {
1776
- name = "label-2p-fm3";
1976
+ // lib/plugins/Label_1L_070.ts
1977
+ var Label_1L_070 = class extends DecoderPlugin {
1978
+ // eslint-disable-line camelcase
1979
+ name = "label-1l-070";
1777
1980
  qualifiers() {
1778
1981
  return {
1779
- labels: ["2P"]
1982
+ labels: ["1L"],
1983
+ preambles: ["000000070"]
1780
1984
  };
1781
1985
  }
1782
1986
  decode(message, options = {}) {
1783
- let decodeResult = this.defaultResult();
1987
+ const decodeResult = this.defaultResult();
1784
1988
  decodeResult.decoder.name = this.name;
1785
- decodeResult.formatted.description = "Flight Report";
1989
+ decodeResult.formatted.description = "Position Report";
1786
1990
  decodeResult.message = message;
1787
- const parts = message.text.split(",");
1788
- if (parts.length === 7) {
1789
- const header = parts[0].split("FM3 ");
1790
- if (header.length == 0) {
1791
- ResultFormatter.unknown(decodeResult, message.text);
1792
- decodeResult.decoded = false;
1793
- decodeResult.decoder.decodeLevel = "none";
1794
- return decodeResult;
1795
- }
1796
- if (header[0].length > 0) {
1797
- ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
1798
- ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
1799
- }
1800
- console.log(header[1]);
1801
- if (header[1].length === 4) {
1802
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
1803
- } else {
1804
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
1805
- }
1806
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[1]));
1807
- const lat = parts[2].replaceAll(" ", "");
1808
- const lon = parts[3].replaceAll(" ", "");
1809
- if (lat[0] === "N" || lat[0] === "S") {
1810
- ResultFormatter.position(decodeResult, {
1811
- latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
1812
- longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
1813
- });
1814
- } else {
1815
- ResultFormatter.position(decodeResult, { latitude: Number(lat), longitude: Number(lon) });
1991
+ if (!message.text.startsWith("000000070")) {
1992
+ if (options.debug) {
1993
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1816
1994
  }
1817
- ResultFormatter.altitude(decodeResult, Number(parts[4]));
1818
- ResultFormatter.unknown(decodeResult, parts[5]);
1819
- ResultFormatter.unknown(decodeResult, parts[6]);
1820
- decodeResult.decoded = true;
1821
- decodeResult.decoder.decodeLevel = "partial";
1822
- } else {
1995
+ decodeResult.remaining.text = message.text;
1996
+ decodeResult.decoded = false;
1997
+ decodeResult.decoder.decodeLevel = "none";
1998
+ return decodeResult;
1999
+ }
2000
+ const parts = message.text.substring(9).split(",");
2001
+ if (parts.length !== 7) {
1823
2002
  if (options.debug) {
1824
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2003
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1825
2004
  }
1826
- ResultFormatter.unknown(decodeResult, message.text);
2005
+ decodeResult.remaining.text = message.text;
1827
2006
  decodeResult.decoded = false;
1828
2007
  decodeResult.decoder.decodeLevel = "none";
2008
+ return decodeResult;
1829
2009
  }
2010
+ ResultFormatter.departureAirport(decodeResult, parts[0]);
2011
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2012
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2]));
2013
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
2014
+ ResultFormatter.position(decodeResult, {
2015
+ latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
2016
+ longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
2017
+ });
2018
+ decodeResult.remaining.text = parts[6];
2019
+ decodeResult.decoded = true;
2020
+ decodeResult.decoder.decodeLevel = "partial";
1830
2021
  return decodeResult;
1831
2022
  }
1832
2023
  };
1833
2024
 
1834
- // lib/plugins/Label_2P_FM4.ts
1835
- var Label_2P_FM4 = class extends DecoderPlugin {
1836
- name = "label-2p-fm4";
2025
+ // lib/plugins/Label_1L_660.ts
2026
+ var Label_1L_660 = class extends DecoderPlugin {
2027
+ // eslint-disable-line camelcase
2028
+ name = "label-1l-660";
1837
2029
  qualifiers() {
1838
2030
  return {
1839
- labels: ["2P"]
2031
+ labels: ["1L"],
2032
+ preambles: ["000000660"]
1840
2033
  };
1841
2034
  }
1842
2035
  decode(message, options = {}) {
1843
- let decodeResult = this.defaultResult();
2036
+ const decodeResult = this.defaultResult();
1844
2037
  decodeResult.decoder.name = this.name;
1845
- decodeResult.formatted.description = "Flight Report";
2038
+ decodeResult.formatted.description = "Position Report";
1846
2039
  decodeResult.message = message;
1847
- const parts = message.text.split(",");
1848
- if (parts.length === 10) {
1849
- const header = parts[0].split("FM4");
1850
- if (header.length == 0) {
1851
- ResultFormatter.unknown(decodeResult, message.text);
1852
- decodeResult.decoded = false;
1853
- decodeResult.decoder.decodeLevel = "none";
1854
- return decodeResult;
1855
- }
1856
- if (header[0].length > 0) {
1857
- ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
1858
- ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2040
+ if (!message.text.startsWith("000000660")) {
2041
+ if (options.debug) {
2042
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1859
2043
  }
1860
- ResultFormatter.departureAirport(decodeResult, header[1]);
1861
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
1862
- ResultFormatter.day(decodeResult, Number(parts[2].substring(0, 2)));
1863
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2].substring(2)));
1864
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
1865
- ResultFormatter.position(decodeResult, { latitude: Number(parts[4].replaceAll(" ", "")), longitude: Number(parts[5].replaceAll(" ", "")) });
1866
- ResultFormatter.altitude(decodeResult, Number(parts[6]));
1867
- ResultFormatter.heading(decodeResult, Number(parts[7]));
1868
- ResultFormatter.unknown(decodeResult, parts[8]);
1869
- ResultFormatter.unknown(decodeResult, parts[9]);
1870
- decodeResult.decoded = true;
1871
- decodeResult.decoder.decodeLevel = "partial";
1872
- } else {
2044
+ decodeResult.remaining.text = message.text;
2045
+ decodeResult.decoded = false;
2046
+ decodeResult.decoder.decodeLevel = "none";
2047
+ return decodeResult;
2048
+ }
2049
+ const parts = message.text.substring(9).split(",");
2050
+ if (parts.length !== 5) {
1873
2051
  if (options.debug) {
1874
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2052
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1875
2053
  }
1876
- ResultFormatter.unknown(decodeResult, message.text);
2054
+ decodeResult.remaining.text = message.text;
1877
2055
  decodeResult.decoded = false;
1878
2056
  decodeResult.decoder.decodeLevel = "none";
2057
+ return decodeResult;
2058
+ }
2059
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(parts[0]);
2060
+ if (position) {
2061
+ ResultFormatter.position(decodeResult, position);
1879
2062
  }
2063
+ const hhmmss = parts[1].substring(0, 6);
2064
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(hhmmss));
2065
+ const fl = parts[1].substring(6, 9);
2066
+ ResultFormatter.altitude(decodeResult, Number(fl) * 100);
2067
+ const next = parts[1].substring(9);
2068
+ ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
2069
+ decodeResult.remaining.text = parts.slice(2).join(",");
2070
+ decodeResult.decoded = true;
2071
+ decodeResult.decoder.decodeLevel = "partial";
1880
2072
  return decodeResult;
1881
2073
  }
1882
2074
  };
1883
2075
 
1884
- // lib/plugins/Label_2P_FM5.ts
1885
- var Label_2P_FM5 = class extends DecoderPlugin {
1886
- name = "label-2p-fm5";
2076
+ // lib/plugins/Label_1L_Slash.ts
2077
+ var Label_1L_Slash = class extends DecoderPlugin {
2078
+ // eslint-disable-line camelcase
2079
+ name = "label-1l-1-line";
1887
2080
  qualifiers() {
1888
2081
  return {
1889
- labels: ["2P"]
2082
+ labels: ["1L"],
2083
+ preambles: ["+", "-"]
1890
2084
  };
1891
2085
  }
1892
2086
  decode(message, options = {}) {
1893
- let decodeResult = this.defaultResult();
2087
+ const decodeResult = this.defaultResult();
1894
2088
  decodeResult.decoder.name = this.name;
1895
- decodeResult.formatted.description = "Flight Report";
2089
+ decodeResult.formatted.description = "Position Report";
1896
2090
  decodeResult.message = message;
1897
- const parts = message.text.split(",");
1898
- if (parts.length === 12) {
1899
- const header = parts[0].split("FM5 ");
1900
- if (header.length == 0) {
1901
- ResultFormatter.unknown(decodeResult, message.text);
1902
- decodeResult.decoded = false;
1903
- decodeResult.decoder.decodeLevel = "none";
1904
- return decodeResult;
1905
- }
1906
- ResultFormatter.departureAirport(decodeResult, header[1]);
1907
- ResultFormatter.arrivalAirport(decodeResult, parts[1]);
1908
- ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2]));
1909
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
1910
- ResultFormatter.position(decodeResult, { latitude: Number(parts[4].replaceAll(" ", "")), longitude: Number(parts[5].replaceAll(" ", "")) });
1911
- ResultFormatter.altitude(decodeResult, Number(parts[6]));
1912
- ResultFormatter.unknown(decodeResult, parts[7]);
1913
- ResultFormatter.unknown(decodeResult, parts[8]);
1914
- ResultFormatter.unknown(decodeResult, parts[9]);
1915
- ResultFormatter.flightNumber(decodeResult, parts[10].trim());
1916
- ResultFormatter.unknown(decodeResult, parts[11]);
1917
- decodeResult.decoded = true;
1918
- decodeResult.decoder.decodeLevel = "partial";
1919
- } else {
2091
+ const parts = message.text.split("/");
2092
+ if (parts.length !== 7) {
1920
2093
  if (options.debug) {
1921
- console.log(`Decoder: Unknown H1 message: ${message.text}`);
2094
+ console.log(`Decoder: Unknown 1L message: ${message.text}`);
1922
2095
  }
1923
- ResultFormatter.unknown(decodeResult, message.text);
2096
+ decodeResult.remaining.text = message.text;
1924
2097
  decodeResult.decoded = false;
1925
2098
  decodeResult.decoder.decodeLevel = "none";
2099
+ return decodeResult;
2100
+ }
2101
+ const data = /* @__PURE__ */ new Map();
2102
+ data.set("LAT", parts[0].replaceAll(" ", ""));
2103
+ data.set("LON", parts[1].replaceAll(" ", ""));
2104
+ for (let i = 2; i < parts.length; i++) {
2105
+ const part = parts[i].split(" ");
2106
+ data.set(part[0], part.slice(1).join(" "));
2107
+ }
2108
+ const position = {
2109
+ latitude: Number(data.get("LAT")),
2110
+ longitude: Number(data.get("LON"))
2111
+ };
2112
+ data.delete("LAT");
2113
+ data.delete("LON");
2114
+ ResultFormatter.position(decodeResult, position);
2115
+ const utc = data.get("UTC");
2116
+ if (utc) {
2117
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(utc));
2118
+ data.delete("UTC");
2119
+ }
2120
+ const alt = data.get("ALT");
2121
+ if (alt) {
2122
+ ResultFormatter.altitude(decodeResult, Number(alt));
2123
+ data.delete("ALT");
2124
+ }
2125
+ const fob = data.get("FOB");
2126
+ if (fob) {
2127
+ ResultFormatter.currentFuel(decodeResult, Number(fob));
2128
+ data.delete("FOB");
2129
+ }
2130
+ const eta = data.get("ETA");
2131
+ if (eta) {
2132
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta));
2133
+ data.delete("ETA");
2134
+ }
2135
+ let remaining = "";
2136
+ for (const [key, value] of data.entries()) {
2137
+ remaining += `/${key} ${value}`;
1926
2138
  }
2139
+ decodeResult.remaining.text = remaining;
2140
+ decodeResult.decoded = true;
2141
+ decodeResult.decoder.decodeLevel = "partial";
1927
2142
  return decodeResult;
1928
2143
  }
1929
2144
  };
1930
2145
 
1931
- // lib/utils/flight_plan_utils.ts
1932
- var FlightPlanUtils = class _FlightPlanUtils {
1933
- /**
1934
- * Processes flight plan data
1935
- *
1936
- * Expected format is [header, key1, val1, ... keyN, valN]
1937
- *
1938
- * @param decodeResult - results
1939
- * @param data - original message split by ':'
1940
- * @returns whether all fields were processed or not
1941
- */
1942
- static processFlightPlan(decodeResult, data) {
1943
- let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
1944
- for (let i = 1; i < data.length; i += 2) {
1945
- const key = data[i];
1946
- const value = data[i + 1];
1947
- switch (key) {
1948
- case "A":
1949
- addProcedure(decodeResult, value, "arrival");
1950
- break;
1951
- case "AA":
1952
- addArrivalAirport(decodeResult, value);
1953
- break;
1954
- case "AP":
1955
- addProcedure(decodeResult, value, "approach");
1956
- break;
1957
- case "CR":
1958
- addCompanyRoute(decodeResult, value);
1959
- break;
1960
- case "D":
1961
- addProcedure(decodeResult, value, "departure");
1962
- break;
1963
- case "DA":
1964
- addDepartureAirport(decodeResult, value);
1965
- break;
1966
- case "F":
1967
- addRoute(decodeResult, value);
1968
- break;
1969
- case "R":
1970
- addRunway(decodeResult, value);
1971
- break;
1972
- // case 'WS': // something about routes, has altitude, so current parsing won't work
1973
- // break;
1974
- default:
1975
- if (allKnownFields) {
1976
- decodeResult.remaining.text = "";
1977
- allKnownFields = false;
1978
- }
1979
- decodeResult.remaining.text += `:${key}:${value}`;
1980
- decodeResult.decoder.decodeLevel = "partial";
1981
- }
1982
- }
1983
- return allKnownFields;
2146
+ // lib/plugins/Label_20_POS.ts
2147
+ var Label_20_POS = class extends DecoderPlugin {
2148
+ name = "label-20-pos";
2149
+ qualifiers() {
2150
+ return {
2151
+ labels: ["20"],
2152
+ preambles: ["POS"]
2153
+ };
1984
2154
  }
1985
- static parseHeader(decodeResult, header) {
1986
- let allKnownFields = true;
1987
- if (header.startsWith("RF")) {
1988
- decodeResult.formatted.items.push({
1989
- type: "status",
1990
- code: "ROUTE_STATUS",
1991
- label: "Route Status",
1992
- value: "Route Filed"
1993
- });
1994
- decodeResult.raw.route_status = "RF";
1995
- if (header.length > 2) {
1996
- addRoute(decodeResult, header.substring(2));
2155
+ decode(message, options = {}) {
2156
+ const decodeResult = this.defaultResult();
2157
+ decodeResult.decoder.name = this.name;
2158
+ decodeResult.formatted.description = "Position Report";
2159
+ decodeResult.message = message;
2160
+ decodeResult.raw.preamble = message.text.substring(0, 3);
2161
+ const content = message.text.substring(3);
2162
+ const fields = content.split(",");
2163
+ if (fields.length == 11) {
2164
+ if (options.debug) {
2165
+ console.log(`DEBUG: ${this.name}: Variation 1 detected`);
1997
2166
  }
1998
- } else if (header.startsWith("RP")) {
1999
- decodeResult.raw.route_status = "RP";
2000
- decodeResult.formatted.items.push({
2001
- type: "status",
2002
- code: "ROUTE_STATUS",
2003
- label: "Route Status",
2004
- value: "Route Planned"
2005
- });
2006
- decodeResult.raw.route_status = header;
2007
- } else if (header.startsWith("RI")) {
2008
- decodeResult.raw.route_status = "RI";
2009
- decodeResult.formatted.items.push({
2010
- type: "status",
2011
- code: "ROUTE_STATUS",
2012
- label: "Route Status",
2013
- value: "Route Inactive"
2014
- });
2167
+ const rawCoords = fields[0];
2168
+ ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(rawCoords));
2169
+ decodeResult.decoded = true;
2170
+ decodeResult.decoder.decodeLevel = "full";
2171
+ } else if (fields.length == 5) {
2172
+ if (options.debug) {
2173
+ console.log(`DEBUG: ${this.name}: Variation 2 detected`);
2174
+ }
2175
+ const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
2176
+ if (position) {
2177
+ ResultFormatter.position(decodeResult, position);
2178
+ }
2179
+ decodeResult.decoded = true;
2180
+ decodeResult.decoder.decodeLevel = "full";
2015
2181
  } else {
2016
- decodeResult.remaining.text += header;
2017
- allKnownFields = false;
2182
+ if (options.debug) {
2183
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
2184
+ }
2185
+ decodeResult.decoded = false;
2186
+ decodeResult.decoder.decodeLevel = "none";
2018
2187
  }
2019
- return allKnownFields;
2188
+ return decodeResult;
2020
2189
  }
2021
2190
  };
2022
- function addArrivalAirport(decodeResult, value) {
2023
- ResultFormatter.arrivalAirport(decodeResult, value);
2024
- }
2025
- function addDepartureAirport(decodeResult, value) {
2026
- ResultFormatter.departureAirport(decodeResult, value);
2027
- }
2028
- function addRunway(decodeResult, value) {
2029
- if (value.length === 8) {
2030
- ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
2031
- }
2032
- ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
2033
- }
2034
- function addRoute(decodeResult, value) {
2035
- const route = value.split(".");
2036
- ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
2037
- }
2038
- function addProcedure(decodeResult, value, type) {
2039
- if (decodeResult.raw.procedures === void 0) {
2040
- decodeResult.raw.procedures = [];
2041
- }
2042
- const data = value.split(".");
2043
- let waypoints;
2044
- if (data.length > 1) {
2045
- waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
2191
+
2192
+ // lib/plugins/Label_21_POS.ts
2193
+ var Label_21_POS = class extends DecoderPlugin {
2194
+ name = "label-21-pos";
2195
+ qualifiers() {
2196
+ return {
2197
+ labels: ["21"],
2198
+ preambles: ["POS"]
2199
+ };
2046
2200
  }
2047
- const route = { name: data[0], waypoints };
2048
- decodeResult.raw.procedures.push({ type, route });
2049
- const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
2050
- let procedureValue = route.name;
2051
- decodeResult.formatted.items.push({
2052
- type: `procedure`,
2053
- code: "proc",
2054
- label: `${procedureName} Procedure`,
2055
- value: RouteUtils.routeToString(route)
2056
- });
2057
- }
2058
- function addCompanyRoute(decodeResult, value) {
2059
- const segments = value.split(".");
2060
- const parens_idx = segments[0].indexOf("(");
2061
- let name;
2062
- let runway;
2063
- if (parens_idx === -1) {
2064
- name = segments[0];
2065
- } else {
2066
- name = segments[0].slice(0, parens_idx);
2067
- runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
2201
+ decode(message, options = {}) {
2202
+ const decodeResult = this.defaultResult();
2203
+ decodeResult.decoder.name = this.name;
2204
+ decodeResult.formatted.description = "Position Report";
2205
+ decodeResult.message = message;
2206
+ decodeResult.raw.preamble = message.text.substring(0, 3);
2207
+ const content = message.text.substring(3);
2208
+ const fields = content.split(",");
2209
+ if (fields.length == 9) {
2210
+ processPosition(decodeResult, fields[0].trim());
2211
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
2212
+ ResultFormatter.altitude(decodeResult, Number(fields[3]));
2213
+ ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
2214
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[7]));
2215
+ ResultFormatter.arrivalAirport(decodeResult, fields[8]);
2216
+ ResultFormatter.unknownArr(decodeResult, [fields[1], fields[4], fields[5]]);
2217
+ decodeResult.decoded = true;
2218
+ decodeResult.decoder.decodeLevel = "partial";
2219
+ } else {
2220
+ if (options.debug) {
2221
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
2222
+ }
2223
+ decodeResult.decoded = false;
2224
+ decodeResult.decoder.decodeLevel = "none";
2225
+ }
2226
+ return decodeResult;
2068
2227
  }
2069
- let waypoints;
2070
- if (segments.length > 1) {
2071
- waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
2228
+ };
2229
+ function processPosition(decodeResult, value) {
2230
+ if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
2231
+ return;
2072
2232
  }
2073
- decodeResult.raw.company_route = {
2074
- name,
2075
- runway,
2076
- waypoints
2233
+ const latDir = value[0] === "N" ? 1 : -1;
2234
+ const lonDir = value[8] === "E" ? 1 : -1;
2235
+ const position = {
2236
+ latitude: latDir * Number(value.substring(1, 7)),
2237
+ longitude: lonDir * Number(value.substring(9, 15))
2077
2238
  };
2078
- decodeResult.formatted.items.push({
2079
- type: "company_route",
2080
- code: "CR",
2081
- label: "Company Route",
2082
- value: RouteUtils.routeToString(decodeResult.raw.company_route)
2083
- });
2239
+ ResultFormatter.position(decodeResult, position);
2084
2240
  }
2085
2241
 
2086
- // lib/utils/h1_helper.ts
2087
- var H1Helper = class _H1Helper {
2088
- static decodeH1Message(decodeResult, message) {
2089
- const checksum = message.slice(-4);
2090
- const data = message.slice(0, message.length - 4);
2091
- const fields = data.split("/");
2092
- const canDecode = parseMessageType(decodeResult, fields[0]);
2093
- if (!canDecode) {
2242
+ // lib/plugins/Label_22_OFF.ts
2243
+ var Label_22_OFF = class extends DecoderPlugin {
2244
+ name = "label-22-off";
2245
+ qualifiers() {
2246
+ return {
2247
+ labels: ["22"],
2248
+ preambles: ["OFF"]
2249
+ };
2250
+ }
2251
+ decode(message, options = {}) {
2252
+ const decodeResult = this.defaultResult();
2253
+ decodeResult.decoder.name = this.name;
2254
+ decodeResult.formatted.description = "Takeoff Report";
2255
+ decodeResult.message = message;
2256
+ if (message.text.startsWith("OFF01")) {
2257
+ const fields = message.text.substring(5).split("/");
2258
+ if (fields.length != 2) {
2259
+ decodeResult.decoded = false;
2260
+ decodeResult.decoder.decodeLevel = "none";
2261
+ return decodeResult;
2262
+ }
2263
+ ResultFormatter.flightNumber(decodeResult, fields[0]);
2264
+ ResultFormatter.departureDay(decodeResult, Number(fields[1].substring(0, 2)));
2265
+ ResultFormatter.arrivalDay(decodeResult, Number(fields[1].substring(2, 4)));
2266
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8)));
2267
+ ResultFormatter.departureAirport(decodeResult, fields[1].substring(8, 12));
2268
+ ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
2269
+ ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22)));
2270
+ ResultFormatter.unknown(decodeResult, fields[1].substring(22));
2271
+ decodeResult.decoded = true;
2272
+ decodeResult.decoder.decodeLevel = "partial";
2273
+ } else if (message.text.startsWith("OFF02\r\n")) {
2274
+ const fields = message.text.substring(7).split(",");
2275
+ if (fields.length != 4) {
2276
+ decodeResult.decoded = false;
2277
+ decodeResult.decoder.decodeLevel = "none";
2278
+ return decodeResult;
2279
+ }
2280
+ ResultFormatter.departureAirport(decodeResult, fields[0]);
2281
+ ResultFormatter.arrivalAirport(decodeResult, fields[1]);
2282
+ ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
2283
+ ResultFormatter.unknown(decodeResult, fields[3]);
2284
+ decodeResult.decoded = true;
2285
+ decodeResult.decoder.decodeLevel = "partial";
2286
+ } else if (message.text.startsWith("OFF02")) {
2287
+ const fields = message.text.substring(5).split("/");
2288
+ if (fields.length != 2) {
2289
+ decodeResult.decoded = false;
2290
+ decodeResult.decoder.decodeLevel = "none";
2291
+ return decodeResult;
2292
+ }
2293
+ ResultFormatter.flightNumber(decodeResult, fields[0]);
2294
+ const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(fields[1].substring(0, 14));
2295
+ if (position) {
2296
+ ResultFormatter.position(decodeResult, position);
2297
+ }
2298
+ ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
2299
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20)));
2300
+ ResultFormatter.departureAirport(decodeResult, fields[1].substring(20, 24));
2301
+ ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
2302
+ ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32)));
2303
+ ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
2304
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40)));
2305
+ decodeResult.decoded = true;
2306
+ decodeResult.decoder.decodeLevel = "partial";
2307
+ } else {
2308
+ if (options.debug) {
2309
+ console.log(`DEBUG: ${this.name}: Unknown variation.`);
2310
+ }
2094
2311
  decodeResult.decoded = false;
2095
2312
  decodeResult.decoder.decodeLevel = "none";
2096
- return false;
2097
2313
  }
2098
- for (let i = 1; i < fields.length; ++i) {
2099
- if (fields[i].startsWith("FN")) {
2100
- decodeResult.raw.flight_number = fields[i].substring(2);
2101
- } else if (fields[i].startsWith("SN")) {
2102
- decodeResult.raw.serial_number = fields[i].substring(2);
2103
- } else if (fields[i].startsWith("DC")) {
2104
- processDC(decodeResult, fields[i].substring(2).split(","));
2105
- } else if (fields[i].startsWith("TS")) {
2106
- _H1Helper.processTS(decodeResult, fields[i].substring(2).split(","));
2107
- } else if (fields[i].startsWith("PS")) {
2108
- _H1Helper.processPS(decodeResult, fields[i].substring(2).split(","));
2109
- } else if (fields[i].startsWith("DT")) {
2110
- const data2 = fields[i].substring(2).split(",");
2111
- processDT(decodeResult, data2);
2112
- } else if (fields[i].startsWith("ID")) {
2113
- processIdentification(decodeResult, fields[i].substring(2).split(","));
2114
- } else if (fields[i].startsWith("LR")) {
2115
- const data2 = fields[i].substring(2).split(",");
2116
- processLR(decodeResult, data2);
2117
- } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
2118
- FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
2119
- } else if (fields[i].startsWith("PR")) {
2120
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2121
- } else if (fields[i].startsWith("AF")) {
2122
- processAirField(decodeResult, fields[i].substring(2).split(","));
2123
- } else if (fields[i].startsWith("TD")) {
2124
- processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
2125
- } else if (fields[i].startsWith("FX")) {
2126
- ResultFormatter.freetext(decodeResult, fields[i].substring(2));
2127
- } else if (fields[i].startsWith("ET")) {
2128
- if (fields[i].length === 7) {
2129
- ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 3)));
2130
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3)));
2131
- } else if (fields[i].length === 8) {
2132
- ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 4)));
2133
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4)));
2134
- } else {
2135
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2136
- }
2137
- } else if (fields[i].startsWith("WD")) {
2138
- processWindData(decodeResult, fields[i].substring(2));
2139
- } else {
2140
- ResultFormatter.unknown(decodeResult, fields[i], "/");
2141
- }
2142
- }
2143
- if (decodeResult.formatted.items.length > 0) {
2144
- ResultFormatter.checksum(decodeResult, checksum);
2145
- }
2146
- return true;
2147
- }
2148
- static processPS(decodeResult, data) {
2149
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
2150
- if (position) {
2151
- decodeResult.raw.position = position;
2152
- decodeResult.formatted.items.push({
2153
- type: "aircraft_position",
2154
- code: "POS",
2155
- label: "Aircraft Position",
2156
- value: CoordinateUtils.coordinateString(position)
2157
- });
2158
- }
2159
- if (data.length === 9) {
2160
- processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
2161
- ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
2162
- ResultFormatter.temperature(decodeResult, data[6]);
2163
- ResultFormatter.unknown(decodeResult, data[7]);
2164
- ResultFormatter.unknown(decodeResult, data[8]);
2165
- }
2166
- if (data.length === 14) {
2167
- ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
2168
- processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
2169
- ResultFormatter.temperature(decodeResult, data[7]);
2170
- ResultFormatter.unknownArr(decodeResult, data.slice(8));
2171
- }
2172
- }
2173
- static processPosition(decodeResult, data) {
2174
- const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
2175
- if (position) {
2176
- ResultFormatter.position(decodeResult, position);
2177
- }
2178
- if (data.length >= 10) {
2179
- ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
2180
- processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
2181
- ResultFormatter.temperature(decodeResult, data[7]);
2182
- ResultFormatter.unknown(decodeResult, data[8]);
2183
- ResultFormatter.unknown(decodeResult, data[9]);
2184
- }
2185
- if (data.length >= 14) {
2186
- ResultFormatter.unknownArr(decodeResult, data.slice(10));
2187
- }
2188
- }
2189
- static processTS(decodeResult, data) {
2190
- let time = DateTimeUtils.convertDateTimeToEpoch(data[0], data[1]);
2191
- if (Number.isNaN(time)) {
2192
- const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
2193
- time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
2194
- }
2195
- decodeResult.raw.message_date = data[1];
2196
- decodeResult.raw.message_timestamp = time;
2314
+ return decodeResult;
2197
2315
  }
2198
2316
  };
2199
- function processAirField(decodeResult, data) {
2200
- if (data.length === 2) {
2201
- ResultFormatter.departureAirport(decodeResult, data[0]);
2202
- ResultFormatter.arrivalAirport(decodeResult, data[1]);
2203
- } else {
2204
- ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
2205
- }
2206
- }
2207
- function processTimeOfDeparture(decodeResult, data) {
2208
- if (data.length === 2) {
2209
- decodeResult.raw.plannedDepartureTime = data[0];
2210
- decodeResult.formatted.items.push({
2211
- type: "ptd",
2212
- code: "ptd",
2213
- label: "Planned Departure Time",
2214
- value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
2215
- });
2216
- decodeResult.raw.plannedDepartureTime = data[1];
2217
- decodeResult.formatted.items.push({
2218
- type: "etd",
2219
- code: "etd",
2220
- label: "Estimated Departure Time",
2221
- value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
2222
- });
2223
- } else {
2224
- ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
2225
- }
2226
- }
2227
- function processIdentification(decodeResult, data) {
2228
- ResultFormatter.tail(decodeResult, data[0]);
2229
- if (data.length > 1) {
2230
- ResultFormatter.flightNumber(decodeResult, data[1]);
2231
- }
2232
- if (data.length > 2) {
2233
- decodeResult.raw.mission_number = data[2];
2234
- }
2235
- }
2236
- function processDT(decodeResult, data) {
2237
- if (!decodeResult.raw.arrival_icao) {
2238
- ResultFormatter.arrivalAirport(decodeResult, data[0]);
2239
- } else if (decodeResult.raw.arrival_icao != data[0]) {
2240
- ResultFormatter.unknownArr(decodeResult, data);
2241
- }
2242
- if (data.length > 1) {
2243
- ResultFormatter.arrivalRunway(decodeResult, data[1]);
2244
- }
2245
- if (data.length > 2) {
2246
- ResultFormatter.currentFuel(decodeResult, Number(data[2]));
2247
- }
2248
- if (data.length > 3) {
2249
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
2250
- }
2251
- if (data.length > 4) {
2252
- ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
2253
- }
2254
- if (data.length > 5) {
2255
- ResultFormatter.unknownArr(decodeResult, data);
2256
- }
2257
- }
2258
- function processLR(decodeResult, data) {
2259
- if (data.length === 19) {
2260
- ResultFormatter.unknown(decodeResult, data[1]);
2261
- ResultFormatter.flightNumber(decodeResult, data[2]);
2262
- ResultFormatter.departureAirport(decodeResult, data[3]);
2263
- ResultFormatter.arrivalAirport(decodeResult, data[4]);
2264
- ResultFormatter.arrivalRunway(decodeResult, data[5]);
2265
- ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
2266
- } else {
2267
- ResultFormatter.unknown(decodeResult, data.join(","));
2317
+
2318
+ // lib/plugins/Label_22_POS.ts
2319
+ var Label_22_POS = class extends DecoderPlugin {
2320
+ name = "label-22-pos";
2321
+ qualifiers() {
2322
+ return {
2323
+ labels: ["22"],
2324
+ preambles: ["N", "S"]
2325
+ };
2268
2326
  }
2269
- }
2270
- function parseMessageType(decodeResult, messageType) {
2271
- const parts = messageType.split("#");
2272
- if (parts.length == 1) {
2273
- const type = parts[0].substring(0, 3);
2274
- if (type === "POS" && parts[0].length !== 3) {
2275
- H1Helper.processPosition(decodeResult, parts[0].substring(3).split(","));
2276
- } else if (parts[0].length > 3 && parts[0].slice(-3) === "POS") {
2277
- ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
2278
- ResultFormatter.flightNumber(decodeResult, parts[0].slice(4, -3));
2279
- return processMessageType(decodeResult, "POS");
2280
- }
2281
- return processMessageType(decodeResult, type);
2282
- } else if (parts.length == 2) {
2283
- if (parts[0].length > 0) {
2284
- ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
2285
- ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
2286
- ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
2327
+ decode(message, options = {}) {
2328
+ const decodeResult = this.defaultResult();
2329
+ decodeResult.decoder.name = this.name;
2330
+ decodeResult.formatted.description = "Position Report";
2331
+ decodeResult.message = message;
2332
+ const fields = message.text.split(",");
2333
+ if (fields.length !== 11) {
2334
+ if (options.debug) {
2335
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`);
2336
+ }
2337
+ decodeResult.decoded = false;
2338
+ decodeResult.decoder.decodeLevel = "none";
2339
+ return decodeResult;
2287
2340
  }
2288
- const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
2289
- if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
2290
- H1Helper.processPosition(decodeResult, parts[1].substring(6).split(","));
2341
+ const latStr = fields[0].substring(1, 8);
2342
+ const lonStr = fields[0].substring(9);
2343
+ const lat = Number(latStr) / 1e4;
2344
+ const lon = Number(lonStr) / 1e4;
2345
+ ResultFormatter.position(decodeResult, {
2346
+ latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
2347
+ longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
2348
+ });
2349
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
2350
+ ResultFormatter.altitude(decodeResult, Number(fields[3]));
2351
+ ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
2352
+ decodeResult.decoded = true;
2353
+ decodeResult.decoder.decodeLevel = "partial";
2354
+ return decodeResult;
2355
+ }
2356
+ };
2357
+
2358
+ // lib/plugins/Label_2P_FM3.ts
2359
+ var Label_2P_FM3 = class extends DecoderPlugin {
2360
+ name = "label-2p-fm3";
2361
+ qualifiers() {
2362
+ return {
2363
+ labels: ["2P"]
2364
+ };
2365
+ }
2366
+ decode(message, options = {}) {
2367
+ let decodeResult = this.defaultResult();
2368
+ decodeResult.decoder.name = this.name;
2369
+ decodeResult.formatted.description = "Flight Report";
2370
+ decodeResult.message = message;
2371
+ const parts = message.text.split(",");
2372
+ if (parts.length === 7) {
2373
+ const header = parts[0].split("FM3 ");
2374
+ if (header.length == 0) {
2375
+ ResultFormatter.unknown(decodeResult, message.text);
2376
+ decodeResult.decoded = false;
2377
+ decodeResult.decoder.decodeLevel = "none";
2378
+ return decodeResult;
2379
+ }
2380
+ if (header[0].length > 0) {
2381
+ ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
2382
+ ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2383
+ }
2384
+ console.log(header[1]);
2385
+ if (header[1].length === 4) {
2386
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
2387
+ } else {
2388
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
2389
+ }
2390
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[1]));
2391
+ const lat = parts[2].replaceAll(" ", "");
2392
+ const lon = parts[3].replaceAll(" ", "");
2393
+ if (lat[0] === "N" || lat[0] === "S") {
2394
+ ResultFormatter.position(decodeResult, {
2395
+ latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
2396
+ longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
2397
+ });
2398
+ } else {
2399
+ ResultFormatter.position(decodeResult, { latitude: Number(lat), longitude: Number(lon) });
2400
+ }
2401
+ ResultFormatter.altitude(decodeResult, Number(parts[4]));
2402
+ ResultFormatter.unknown(decodeResult, parts[5]);
2403
+ ResultFormatter.unknown(decodeResult, parts[6]);
2404
+ decodeResult.decoded = true;
2405
+ decodeResult.decoder.decodeLevel = "partial";
2406
+ } else {
2407
+ if (options.debug) {
2408
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2409
+ }
2410
+ ResultFormatter.unknown(decodeResult, message.text);
2411
+ decodeResult.decoded = false;
2412
+ decodeResult.decoder.decodeLevel = "none";
2291
2413
  }
2292
- return processMessageType(decodeResult, type);
2293
- } else {
2294
- ResultFormatter.unknown(decodeResult, messageType);
2295
- return false;
2414
+ return decodeResult;
2296
2415
  }
2297
- }
2298
- function processMessageType(decodeResult, type) {
2299
- if (type === "FPN") {
2300
- decodeResult.formatted.description = "Flight Plan";
2301
- } else if (type === "FTX") {
2302
- decodeResult.formatted.description = "Free Text";
2303
- } else if (type === "INI") {
2304
- decodeResult.formatted.description = "Flight Plan Initial Report";
2305
- } else if (type === "POS") {
2306
- decodeResult.formatted.description = "Position Report";
2307
- } else if (type === "PRG") {
2308
- decodeResult.formatted.description = "Progress Report";
2309
- } else if (type === "PWI") {
2310
- decodeResult.formatted.description = "Weather Report";
2311
- } else {
2312
- decodeResult.formatted.description = "Unknown H1 Message";
2313
- return false;
2416
+ };
2417
+
2418
+ // lib/plugins/Label_2P_FM4.ts
2419
+ var Label_2P_FM4 = class extends DecoderPlugin {
2420
+ name = "label-2p-fm4";
2421
+ qualifiers() {
2422
+ return {
2423
+ labels: ["2P"]
2424
+ };
2314
2425
  }
2315
- return true;
2316
- }
2317
- function processDC(decodeResult, data) {
2318
- decodeResult.raw.message_date = data[0];
2319
- if (data.length === 1) {
2320
- } else if (data.length === 2) {
2321
- const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
2322
- const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
2323
- decodeResult.raw.message_timestamp = time;
2426
+ decode(message, options = {}) {
2427
+ let decodeResult = this.defaultResult();
2428
+ decodeResult.decoder.name = this.name;
2429
+ decodeResult.formatted.description = "Flight Report";
2430
+ decodeResult.message = message;
2431
+ const parts = message.text.split(",");
2432
+ if (parts.length === 10) {
2433
+ const header = parts[0].split("FM4");
2434
+ if (header.length == 0) {
2435
+ ResultFormatter.unknown(decodeResult, message.text);
2436
+ decodeResult.decoded = false;
2437
+ decodeResult.decoder.decodeLevel = "none";
2438
+ return decodeResult;
2439
+ }
2440
+ if (header[0].length > 0) {
2441
+ ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
2442
+ ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
2443
+ }
2444
+ ResultFormatter.departureAirport(decodeResult, header[1]);
2445
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2446
+ ResultFormatter.day(decodeResult, Number(parts[2].substring(0, 2)));
2447
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2].substring(2)));
2448
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
2449
+ ResultFormatter.position(decodeResult, { latitude: Number(parts[4].replaceAll(" ", "")), longitude: Number(parts[5].replaceAll(" ", "")) });
2450
+ ResultFormatter.altitude(decodeResult, Number(parts[6]));
2451
+ ResultFormatter.heading(decodeResult, Number(parts[7]));
2452
+ ResultFormatter.unknown(decodeResult, parts[8]);
2453
+ ResultFormatter.unknown(decodeResult, parts[9]);
2454
+ decodeResult.decoded = true;
2455
+ decodeResult.decoder.decodeLevel = "partial";
2456
+ } else {
2457
+ if (options.debug) {
2458
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2459
+ }
2460
+ ResultFormatter.unknown(decodeResult, message.text);
2461
+ decodeResult.decoded = false;
2462
+ decodeResult.decoder.decodeLevel = "none";
2463
+ }
2464
+ return decodeResult;
2324
2465
  }
2325
- }
2326
- function processRoute(decodeResult, last, time, next, eta, then, date) {
2327
- const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
2328
- const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
2329
- const timeFormat = date ? "epoch" : "tod";
2330
- const lastWaypoint = RouteUtils.getWaypoint(last);
2331
- lastWaypoint.time = lastTime;
2332
- lastWaypoint.timeFormat = timeFormat;
2333
- const nextWaypoint = RouteUtils.getWaypoint(next);
2334
- nextWaypoint.time = nextTime;
2335
- nextWaypoint.timeFormat = timeFormat;
2336
- const thenWaypoint = RouteUtils.getWaypoint(then || "?");
2337
- const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
2338
- decodeResult.raw.route = { waypoints };
2339
- decodeResult.formatted.items.push({
2340
- type: "aircraft_route",
2341
- code: "ROUTE",
2342
- label: "Aircraft Route",
2343
- value: RouteUtils.routeToString(decodeResult.raw.route)
2344
- });
2345
- }
2346
- function processWindData(decodeResult, message) {
2347
- if (decodeResult.raw.wind_data === void 0) {
2348
- decodeResult.raw.wind_data = [];
2466
+ };
2467
+
2468
+ // lib/plugins/Label_2P_FM5.ts
2469
+ var Label_2P_FM5 = class extends DecoderPlugin {
2470
+ name = "label-2p-fm5";
2471
+ qualifiers() {
2472
+ return {
2473
+ labels: ["2P"]
2474
+ };
2349
2475
  }
2350
- const flightLevel = Number(message.slice(0, 3));
2351
- const fields = message.slice(4).split(".");
2352
- fields.forEach((field) => {
2353
- const data = field.split(",");
2354
- const waypoint = data[0];
2355
- const windData = data[1];
2356
- const windDirection = Number(windData.slice(0, 3));
2357
- const windSpeed = Number(windData.slice(3));
2358
- if (data.length === 3) {
2359
- const tempData = data[2];
2360
- const tempFlightLevel = Number(tempData.slice(0, 3));
2361
- const tempString = tempData.slice(3);
2362
- const tempDegrees = Number(tempString.substring(1)) * (tempString.charAt(0) === "M" ? -1 : 1);
2363
- decodeResult.raw.wind_data.push({
2364
- waypoint,
2365
- flightLevel,
2366
- windDirection,
2367
- windSpeed,
2368
- temperature: {
2369
- flightLevel: tempFlightLevel,
2370
- degreesC: tempDegrees
2371
- }
2372
- });
2373
- decodeResult.formatted.items.push({
2374
- type: "wind_data",
2375
- code: "WIND",
2376
- label: "Wind Data",
2377
- value: `${waypoint} at FL${flightLevel}: ${windDirection}\xB0 at ${windSpeed}kt, ${tempDegrees}\xB0C at FL${tempFlightLevel}`
2378
- });
2476
+ decode(message, options = {}) {
2477
+ let decodeResult = this.defaultResult();
2478
+ decodeResult.decoder.name = this.name;
2479
+ decodeResult.formatted.description = "Flight Report";
2480
+ decodeResult.message = message;
2481
+ const parts = message.text.split(",");
2482
+ if (parts.length === 12) {
2483
+ const header = parts[0].split("FM5 ");
2484
+ if (header.length == 0) {
2485
+ ResultFormatter.unknown(decodeResult, message.text);
2486
+ decodeResult.decoded = false;
2487
+ decodeResult.decoder.decodeLevel = "none";
2488
+ return decodeResult;
2489
+ }
2490
+ ResultFormatter.departureAirport(decodeResult, header[1]);
2491
+ ResultFormatter.arrivalAirport(decodeResult, parts[1]);
2492
+ ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2]));
2493
+ ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3]));
2494
+ ResultFormatter.position(decodeResult, { latitude: Number(parts[4].replaceAll(" ", "")), longitude: Number(parts[5].replaceAll(" ", "")) });
2495
+ ResultFormatter.altitude(decodeResult, Number(parts[6]));
2496
+ ResultFormatter.unknown(decodeResult, parts[7]);
2497
+ ResultFormatter.unknown(decodeResult, parts[8]);
2498
+ ResultFormatter.unknown(decodeResult, parts[9]);
2499
+ ResultFormatter.flightNumber(decodeResult, parts[10].trim());
2500
+ ResultFormatter.unknown(decodeResult, parts[11]);
2501
+ decodeResult.decoded = true;
2502
+ decodeResult.decoder.decodeLevel = "partial";
2379
2503
  } else {
2380
- decodeResult.raw.wind_data.push({
2381
- waypoint,
2382
- flightLevel,
2383
- windDirection,
2384
- windSpeed
2385
- });
2386
- decodeResult.formatted.items.push({
2387
- type: "wind_data",
2388
- code: "WIND",
2389
- label: "Wind Data",
2390
- value: `${waypoint} at FL${flightLevel}: ${windDirection}\xB0 at ${windSpeed}kt`
2391
- });
2504
+ if (options.debug) {
2505
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
2506
+ }
2507
+ ResultFormatter.unknown(decodeResult, message.text);
2508
+ decodeResult.decoded = false;
2509
+ decodeResult.decoder.decodeLevel = "none";
2392
2510
  }
2393
- });
2394
- }
2511
+ return decodeResult;
2512
+ }
2513
+ };
2395
2514
 
2396
2515
  // lib/plugins/Label_2P_POS.ts
2397
2516
  var Label_2P_POS = class extends DecoderPlugin {
@@ -2760,7 +2879,10 @@ var Label_4A = class extends DecoderPlugin {
2760
2879
  ResultFormatter.callsign(decodeResult, fields[3]);
2761
2880
  ResultFormatter.departureAirport(decodeResult, fields[4]);
2762
2881
  ResultFormatter.arrivalAirport(decodeResult, fields[5]);
2763
- ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
2882
+ const alt = text.substring(48, 51);
2883
+ if (alt !== "") {
2884
+ ResultFormatter.altitude(decodeResult, Number(alt) * 100);
2885
+ }
2764
2886
  ResultFormatter.unknownArr(decodeResult, fields.slice(8));
2765
2887
  } else if (fields.length === 6) {
2766
2888
  if (fields[0].match(/^[NS]/)) {
@@ -4835,6 +4957,9 @@ var MessageDecoder = class {
4835
4957
  this.registerPlugin(new Label_15(this));
4836
4958
  this.registerPlugin(new Label_15_FST(this));
4837
4959
  this.registerPlugin(new Label_16_N_Space(this));
4960
+ this.registerPlugin(new Label_16_POSA1(this));
4961
+ this.registerPlugin(new Label_16_TOD(this));
4962
+ this.registerPlugin(new Label_1J_2J_FTX(this));
4838
4963
  this.registerPlugin(new Label_1L_3Line(this));
4839
4964
  this.registerPlugin(new Label_1L_070(this));
4840
4965
  this.registerPlugin(new Label_1L_660(this));