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