@airframes/acars-decoder 1.6.7 → 1.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +695 -371
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +695 -371
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -208,6 +208,12 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
208
208
|
|
|
209
209
|
// lib/utils/coordinate_utils.ts
|
|
210
210
|
var CoordinateUtils = class {
|
|
211
|
+
/**
|
|
212
|
+
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
213
|
+
* @param stringCoords - The string of coordinates to decode
|
|
214
|
+
*
|
|
215
|
+
* @returns An object with latitude and longitude properties
|
|
216
|
+
*/
|
|
211
217
|
static decodeStringCoordinates(stringCoords) {
|
|
212
218
|
var results = {};
|
|
213
219
|
const firstChar = stringCoords.substring(0, 1);
|
|
@@ -225,6 +231,33 @@ var CoordinateUtils = class {
|
|
|
225
231
|
}
|
|
226
232
|
return results;
|
|
227
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
|
|
236
|
+
* @param stringCoords - The string of coordinates to decode
|
|
237
|
+
*
|
|
238
|
+
* @returns An object with latitude and longitude properties
|
|
239
|
+
*/
|
|
240
|
+
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
241
|
+
var results = {};
|
|
242
|
+
const firstChar = stringCoords.substring(0, 1);
|
|
243
|
+
let middleChar = stringCoords.substring(6, 7);
|
|
244
|
+
let longitudeChars = stringCoords.substring(7, 13);
|
|
245
|
+
if (middleChar == " ") {
|
|
246
|
+
middleChar = stringCoords.substring(7, 8);
|
|
247
|
+
longitudeChars = stringCoords.substring(8, 14);
|
|
248
|
+
}
|
|
249
|
+
const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
|
|
250
|
+
const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
|
|
251
|
+
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
252
|
+
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
253
|
+
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
254
|
+
results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
|
|
255
|
+
results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
|
|
256
|
+
} else {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
return results;
|
|
260
|
+
}
|
|
228
261
|
static coordinateString(coords) {
|
|
229
262
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
230
263
|
const lonDir = coords.longitude > 0 ? "E" : "W";
|
|
@@ -595,6 +628,96 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
595
628
|
}
|
|
596
629
|
};
|
|
597
630
|
|
|
631
|
+
// lib/plugins/Label_21_POS.ts
|
|
632
|
+
var Label_21_POS = class extends DecoderPlugin {
|
|
633
|
+
name = "label-21-pos";
|
|
634
|
+
qualifiers() {
|
|
635
|
+
return {
|
|
636
|
+
labels: ["21"],
|
|
637
|
+
preambles: ["POS"]
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
decode(message, options = {}) {
|
|
641
|
+
const decodeResult = this.defaultResult();
|
|
642
|
+
decodeResult.decoder.name = this.name;
|
|
643
|
+
decodeResult.formatted.description = "Position Report";
|
|
644
|
+
decodeResult.message = message;
|
|
645
|
+
decodeResult.raw.preamble = message.text.substring(0, 3);
|
|
646
|
+
const content = message.text.substring(3);
|
|
647
|
+
console.log("Content: " + content);
|
|
648
|
+
const fields = content.split(",");
|
|
649
|
+
console.log("Field Count: " + fields.length);
|
|
650
|
+
if (fields.length == 9) {
|
|
651
|
+
processPosition(decodeResult, fields[0].trim());
|
|
652
|
+
processAlt(decodeResult, fields[3]);
|
|
653
|
+
processTemp(decodeResult, fields[6]);
|
|
654
|
+
processArrvApt(decodeResult, fields[8]);
|
|
655
|
+
decodeResult.raw.remaining = [
|
|
656
|
+
fields[1],
|
|
657
|
+
fields[2],
|
|
658
|
+
fields[4],
|
|
659
|
+
fields[5],
|
|
660
|
+
fields[7]
|
|
661
|
+
].join(",");
|
|
662
|
+
decodeResult.decoded = true;
|
|
663
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
664
|
+
} else {
|
|
665
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
|
|
666
|
+
decodeResult.decoded = false;
|
|
667
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
668
|
+
}
|
|
669
|
+
return decodeResult;
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
function processPosition(decodeResult, value) {
|
|
673
|
+
if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
const latDir = value[0] === "N" ? 1 : -1;
|
|
677
|
+
const lonDir = value[8] === "E" ? 1 : -1;
|
|
678
|
+
const position = {
|
|
679
|
+
latitude: latDir * Number(value.substring(1, 7)),
|
|
680
|
+
longitude: lonDir * Number(value.substring(9, 15))
|
|
681
|
+
};
|
|
682
|
+
if (position) {
|
|
683
|
+
decodeResult.raw.position = position;
|
|
684
|
+
decodeResult.formatted.items.push({
|
|
685
|
+
type: "aircraft_position",
|
|
686
|
+
code: "POS",
|
|
687
|
+
label: "Aircraft Position",
|
|
688
|
+
value: CoordinateUtils.coordinateString(position)
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
return !!position;
|
|
692
|
+
}
|
|
693
|
+
function processAlt(decodeResult, value) {
|
|
694
|
+
decodeResult.raw.altitude = Number(value);
|
|
695
|
+
decodeResult.formatted.items.push({
|
|
696
|
+
type: "altitude",
|
|
697
|
+
code: "ALT",
|
|
698
|
+
label: "Altitude",
|
|
699
|
+
value: `${decodeResult.raw.altitude} feet`
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
function processTemp(decodeResult, value) {
|
|
703
|
+
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
704
|
+
decodeResult.formatted.items.push({
|
|
705
|
+
type: "outside_air_temperature",
|
|
706
|
+
code: "OATEMP",
|
|
707
|
+
label: "Outside Air Temperature (C)",
|
|
708
|
+
value: `${decodeResult.raw.outside_air_temperature}`
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
function processArrvApt(decodeResult, value) {
|
|
712
|
+
decodeResult.raw.arrival_icao = value;
|
|
713
|
+
decodeResult.formatted.items.push({
|
|
714
|
+
type: "destination",
|
|
715
|
+
code: "DST",
|
|
716
|
+
label: "Destination",
|
|
717
|
+
value: decodeResult.raw.arrival_icao
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
598
721
|
// lib/plugins/Label_30_Slash_EA.ts
|
|
599
722
|
var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
600
723
|
name = "label-30-slash-ea";
|
|
@@ -892,7 +1015,7 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
892
1015
|
console.log(`Label 44 Position Report: groups`);
|
|
893
1016
|
console.log(results.groups);
|
|
894
1017
|
}
|
|
895
|
-
decodeResult.raw.position = CoordinateUtils.
|
|
1018
|
+
decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
|
|
896
1019
|
decodeResult.raw.flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? "0" : Number(results.groups.flight_level_or_ground);
|
|
897
1020
|
decodeResult.raw.departure_icao = results.groups.departure_icao;
|
|
898
1021
|
decodeResult.raw.arrival_icao = results.groups.arrival_icao;
|
|
@@ -907,9 +1030,9 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
907
1030
|
}
|
|
908
1031
|
if (decodeResult.raw.position) {
|
|
909
1032
|
decodeResult.formatted.items.push({
|
|
910
|
-
type: "
|
|
1033
|
+
type: "aircraft_position",
|
|
911
1034
|
code: "POS",
|
|
912
|
-
label: "Position",
|
|
1035
|
+
label: "Aircraft Position",
|
|
913
1036
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
914
1037
|
});
|
|
915
1038
|
}
|
|
@@ -1217,6 +1340,168 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
1217
1340
|
}
|
|
1218
1341
|
};
|
|
1219
1342
|
|
|
1343
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
1344
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
1345
|
+
name = "label-h1-flr";
|
|
1346
|
+
qualifiers() {
|
|
1347
|
+
return {
|
|
1348
|
+
labels: ["H1"],
|
|
1349
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
decode(message, options = {}) {
|
|
1353
|
+
let decodeResult = this.defaultResult();
|
|
1354
|
+
decodeResult.decoder.name = this.name;
|
|
1355
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
1356
|
+
decodeResult.message = message;
|
|
1357
|
+
const parts = message.text.split("/FR");
|
|
1358
|
+
if (parts.length > 1) {
|
|
1359
|
+
decodeResult.remaining.text = "";
|
|
1360
|
+
const fields = parts[0].split("/");
|
|
1361
|
+
for (let i = 1; i < fields.length; i++) {
|
|
1362
|
+
const field = fields[i];
|
|
1363
|
+
if (field.startsWith("PN")) {
|
|
1364
|
+
processUnknown(decodeResult, "/" + field);
|
|
1365
|
+
} else {
|
|
1366
|
+
processUnknown(decodeResult, "/" + field);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
const data = parts[1].substring(0, 20);
|
|
1370
|
+
const msg = parts[1].substring(20);
|
|
1371
|
+
const datetime = data.substring(0, 12);
|
|
1372
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
1373
|
+
processUnknown(decodeResult, data.substring(12));
|
|
1374
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
1375
|
+
decodeResult.raw.fault_message = msg;
|
|
1376
|
+
decodeResult.formatted.items.push({
|
|
1377
|
+
type: "fault",
|
|
1378
|
+
code: "FR",
|
|
1379
|
+
label: "Fault Report",
|
|
1380
|
+
value: decodeResult.raw.fault_message
|
|
1381
|
+
});
|
|
1382
|
+
decodeResult.decoded = true;
|
|
1383
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1384
|
+
} else {
|
|
1385
|
+
if (options.debug) {
|
|
1386
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1387
|
+
}
|
|
1388
|
+
decodeResult.remaining.text = message.text;
|
|
1389
|
+
decodeResult.decoded = false;
|
|
1390
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1391
|
+
}
|
|
1392
|
+
return decodeResult;
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
function processUnknown(decodeResult, value) {
|
|
1396
|
+
decodeResult.remaining.text += value;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// lib/utils/result_formatter.ts
|
|
1400
|
+
var ResultFormatter = class {
|
|
1401
|
+
static altitude(decodeResult, value) {
|
|
1402
|
+
decodeResult.raw.altitude = value;
|
|
1403
|
+
decodeResult.formatted.items.push({
|
|
1404
|
+
type: "altitude",
|
|
1405
|
+
code: "ALT",
|
|
1406
|
+
label: "Altitude",
|
|
1407
|
+
value: `${decodeResult.raw.altitude} feet`
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
static flightNumber(decodeResult, value) {
|
|
1411
|
+
decodeResult.raw.flight_number = value;
|
|
1412
|
+
}
|
|
1413
|
+
static departureAirport(decodeResult, value) {
|
|
1414
|
+
decodeResult.raw.departure_icao = value;
|
|
1415
|
+
decodeResult.formatted.items.push({
|
|
1416
|
+
type: "origin",
|
|
1417
|
+
code: "ORG",
|
|
1418
|
+
label: "Origin",
|
|
1419
|
+
value: decodeResult.raw.departure_icao
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
static departureRunway(decodeResult, value) {
|
|
1423
|
+
decodeResult.raw.departure_runway = value;
|
|
1424
|
+
decodeResult.formatted.items.push({
|
|
1425
|
+
type: "runway",
|
|
1426
|
+
code: "DEPRWY",
|
|
1427
|
+
label: "Departure Runway",
|
|
1428
|
+
value: decodeResult.raw.departure_runway
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
static arrivalAirport(decodeResult, value) {
|
|
1432
|
+
decodeResult.raw.arrival_icao = value;
|
|
1433
|
+
decodeResult.formatted.items.push({
|
|
1434
|
+
type: "destination",
|
|
1435
|
+
code: "DST",
|
|
1436
|
+
label: "Destination",
|
|
1437
|
+
value: decodeResult.raw.arrival_icao
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
static eta(decodeResult, value) {
|
|
1441
|
+
decodeResult.formatted.items.push({
|
|
1442
|
+
type: "eta",
|
|
1443
|
+
code: "ETA",
|
|
1444
|
+
label: "Estimated Time of Arrival",
|
|
1445
|
+
value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
static arrivalRunway(decodeResult, value) {
|
|
1449
|
+
decodeResult.raw.arrival_runway = value;
|
|
1450
|
+
decodeResult.formatted.items.push({
|
|
1451
|
+
type: "runway",
|
|
1452
|
+
label: "Arrival Runway",
|
|
1453
|
+
value: decodeResult.raw.arrival_runway
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
static currentFuel(decodeResult, value) {
|
|
1457
|
+
decodeResult.raw.fuel_on_board = value;
|
|
1458
|
+
decodeResult.formatted.items.push({
|
|
1459
|
+
type: "fuel_on_board",
|
|
1460
|
+
code: "FOB",
|
|
1461
|
+
label: "Fuel On Board",
|
|
1462
|
+
value: decodeResult.raw.fuel_on_board.toString()
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
static remainingFuel(decodeResult, value) {
|
|
1466
|
+
decodeResult.raw.fuel_remaining = value;
|
|
1467
|
+
decodeResult.formatted.items.push({
|
|
1468
|
+
type: "fuel_remaining",
|
|
1469
|
+
label: "Fuel Remaining",
|
|
1470
|
+
value: decodeResult.raw.fuel_remaining.toString()
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
static checksum(decodeResult, value) {
|
|
1474
|
+
decodeResult.raw.checksum = Number("0x" + value);
|
|
1475
|
+
decodeResult.formatted.items.push({
|
|
1476
|
+
type: "message_checksum",
|
|
1477
|
+
code: "CHECKSUM",
|
|
1478
|
+
label: "Message Checksum",
|
|
1479
|
+
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
static groundspeed(decodeResult, value) {
|
|
1483
|
+
decodeResult.raw.groundspeed = value;
|
|
1484
|
+
decodeResult.formatted.items.push({
|
|
1485
|
+
type: "aircraft_groundspeed",
|
|
1486
|
+
code: "GSPD",
|
|
1487
|
+
label: "Aircraft Groundspeed",
|
|
1488
|
+
value: `${decodeResult.raw.groundspeed}`
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1491
|
+
static temperature(decodeResult, value) {
|
|
1492
|
+
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1493
|
+
decodeResult.formatted.items.push({
|
|
1494
|
+
type: "outside_air_temperature",
|
|
1495
|
+
code: "OATEMP",
|
|
1496
|
+
label: "Outside Air Temperature (C)",
|
|
1497
|
+
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
static unknown(decodeResult, value) {
|
|
1501
|
+
decodeResult.remaining.text += "," + value;
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
|
|
1220
1505
|
// lib/utils/route_utils.ts
|
|
1221
1506
|
var RouteUtils = class _RouteUtils {
|
|
1222
1507
|
static routeToString(route) {
|
|
@@ -1257,13 +1542,13 @@ var RouteUtils = class _RouteUtils {
|
|
|
1257
1542
|
}
|
|
1258
1543
|
const waypoint = leg.split(",");
|
|
1259
1544
|
if (waypoint.length == 2) {
|
|
1260
|
-
const position = CoordinateUtils.
|
|
1545
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
1261
1546
|
if (position) {
|
|
1262
1547
|
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
1263
1548
|
}
|
|
1264
1549
|
}
|
|
1265
1550
|
if (leg.length == 13 || leg.length == 14) {
|
|
1266
|
-
const position = CoordinateUtils.
|
|
1551
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
1267
1552
|
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
1268
1553
|
if (position) {
|
|
1269
1554
|
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
@@ -1342,146 +1627,52 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1342
1627
|
}
|
|
1343
1628
|
static parseHeader(decodeResult, header) {
|
|
1344
1629
|
let allKnownFields = true;
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
if (Number.isNaN(time)) {
|
|
1356
|
-
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
1357
|
-
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
1358
|
-
}
|
|
1359
|
-
decodeResult.raw.message_timestamp = time;
|
|
1360
|
-
} else if (fields[i].startsWith("PS")) {
|
|
1361
|
-
const pos = fields[i].substring(2);
|
|
1362
|
-
allKnownFields == allKnownFields && processPosition(decodeResult, pos);
|
|
1363
|
-
} else if (fields[i].startsWith("DT")) {
|
|
1364
|
-
const icao = fields[i].substring(2);
|
|
1365
|
-
decodeResult.raw.arrival_icao = icao;
|
|
1366
|
-
decodeResult.formatted.items.push({
|
|
1367
|
-
type: "destination",
|
|
1368
|
-
code: "DST",
|
|
1369
|
-
label: "Destination",
|
|
1370
|
-
value: decodeResult.raw.arrival_icao
|
|
1371
|
-
});
|
|
1372
|
-
} else if (fields[i].startsWith("ID")) {
|
|
1373
|
-
const tail = fields[i].substring(2);
|
|
1374
|
-
decodeResult.raw.tail = tail;
|
|
1375
|
-
decodeResult.formatted.items.push({
|
|
1376
|
-
type: "tail",
|
|
1377
|
-
label: "Tail",
|
|
1378
|
-
value: decodeResult.raw.tail
|
|
1379
|
-
});
|
|
1380
|
-
} else if (fields[i].startsWith("RF")) {
|
|
1381
|
-
decodeResult.formatted.items.push({
|
|
1382
|
-
type: "status",
|
|
1383
|
-
code: "ROUTE_STATUS",
|
|
1384
|
-
label: "Route Status",
|
|
1385
|
-
value: "Route Filed"
|
|
1386
|
-
});
|
|
1387
|
-
decodeResult.raw.route_status = "RF";
|
|
1388
|
-
if (fields[i].length > 2) {
|
|
1389
|
-
addRoute(decodeResult, fields[i].substring(2));
|
|
1390
|
-
}
|
|
1391
|
-
} else if (fields[i] == "RP") {
|
|
1392
|
-
decodeResult.raw.route_status = "RP";
|
|
1393
|
-
decodeResult.formatted.items.push({
|
|
1394
|
-
type: "status",
|
|
1395
|
-
code: "ROUTE_STATUS",
|
|
1396
|
-
label: "Route Status",
|
|
1397
|
-
value: "Route Planned"
|
|
1398
|
-
});
|
|
1399
|
-
decodeResult.raw.route_status = fields[i];
|
|
1400
|
-
} else if (fields[i] == "RI") {
|
|
1401
|
-
decodeResult.raw.route_status = "RI";
|
|
1402
|
-
decodeResult.formatted.items.push({
|
|
1403
|
-
type: "status",
|
|
1404
|
-
code: "ROUTE_STATUS",
|
|
1405
|
-
label: "Route Status",
|
|
1406
|
-
value: "Route Inactive"
|
|
1407
|
-
});
|
|
1408
|
-
} else {
|
|
1409
|
-
decodeResult.remaining.text += "/" + fields[i];
|
|
1410
|
-
allKnownFields = false;
|
|
1630
|
+
if (header.startsWith("RF")) {
|
|
1631
|
+
decodeResult.formatted.items.push({
|
|
1632
|
+
type: "status",
|
|
1633
|
+
code: "ROUTE_STATUS",
|
|
1634
|
+
label: "Route Status",
|
|
1635
|
+
value: "Route Filed"
|
|
1636
|
+
});
|
|
1637
|
+
decodeResult.raw.route_status = "RF";
|
|
1638
|
+
if (header.length > 2) {
|
|
1639
|
+
addRoute(decodeResult, header.substring(2));
|
|
1411
1640
|
}
|
|
1641
|
+
} else if (header.startsWith("RP")) {
|
|
1642
|
+
decodeResult.raw.route_status = "RP";
|
|
1643
|
+
decodeResult.formatted.items.push({
|
|
1644
|
+
type: "status",
|
|
1645
|
+
code: "ROUTE_STATUS",
|
|
1646
|
+
label: "Route Status",
|
|
1647
|
+
value: "Route Planned"
|
|
1648
|
+
});
|
|
1649
|
+
decodeResult.raw.route_status = header;
|
|
1650
|
+
} else if (header.startsWith("RI")) {
|
|
1651
|
+
decodeResult.raw.route_status = "RI";
|
|
1652
|
+
decodeResult.formatted.items.push({
|
|
1653
|
+
type: "status",
|
|
1654
|
+
code: "ROUTE_STATUS",
|
|
1655
|
+
label: "Route Status",
|
|
1656
|
+
value: "Route Inactive"
|
|
1657
|
+
});
|
|
1658
|
+
} else {
|
|
1659
|
+
decodeResult.remaining.text += header;
|
|
1660
|
+
allKnownFields = false;
|
|
1412
1661
|
}
|
|
1413
1662
|
return allKnownFields;
|
|
1414
1663
|
}
|
|
1415
1664
|
};
|
|
1416
|
-
function
|
|
1417
|
-
|
|
1418
|
-
const parts = messageType.split("#");
|
|
1419
|
-
if (parts.length == 1) {
|
|
1420
|
-
if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
|
|
1421
|
-
decoded = processPosition(decodeResult, parts[0].substring(3));
|
|
1422
|
-
}
|
|
1423
|
-
return decoded;
|
|
1424
|
-
} else if (parts.length == 2) {
|
|
1425
|
-
if (parts[0].length > 0) {
|
|
1426
|
-
decodeResult.remaining.text += parts[0].substring(0, 3);
|
|
1427
|
-
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
1428
|
-
decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
|
|
1429
|
-
}
|
|
1430
|
-
if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
|
|
1431
|
-
decoded = processPosition(decodeResult, parts[1].substring(6));
|
|
1432
|
-
}
|
|
1433
|
-
decodeResult.raw.message_type = messageType;
|
|
1434
|
-
return decoded;
|
|
1435
|
-
}
|
|
1436
|
-
decodeResult.remaining.text += messageType;
|
|
1437
|
-
return false;
|
|
1665
|
+
function addArrivalAirport(decodeResult, value) {
|
|
1666
|
+
ResultFormatter.arrivalAirport(decodeResult, value);
|
|
1438
1667
|
}
|
|
1439
|
-
function
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
code: "POS",
|
|
1446
|
-
label: "Aircraft Position",
|
|
1447
|
-
value: CoordinateUtils.coordinateString(position)
|
|
1448
|
-
});
|
|
1668
|
+
function addDepartureAirport(decodeResult, value) {
|
|
1669
|
+
ResultFormatter.departureAirport(decodeResult, value);
|
|
1670
|
+
}
|
|
1671
|
+
function addRunway(decodeResult, value) {
|
|
1672
|
+
if (value.length === 8) {
|
|
1673
|
+
ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
|
|
1449
1674
|
}
|
|
1450
|
-
|
|
1451
|
-
}
|
|
1452
|
-
function addArrivalAirport(decodeResult, value) {
|
|
1453
|
-
decodeResult.raw.arrival_icao = value;
|
|
1454
|
-
decodeResult.formatted.items.push({
|
|
1455
|
-
type: "destination",
|
|
1456
|
-
code: "DST",
|
|
1457
|
-
label: "Destination",
|
|
1458
|
-
value: decodeResult.raw.arrival_icao
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
function addDepartureAirport(decodeResult, value) {
|
|
1462
|
-
decodeResult.raw.departure_icao = value;
|
|
1463
|
-
decodeResult.formatted.items.push({
|
|
1464
|
-
type: "origin",
|
|
1465
|
-
code: "ORG",
|
|
1466
|
-
label: "Origin",
|
|
1467
|
-
value: decodeResult.raw.departure_icao
|
|
1468
|
-
});
|
|
1469
|
-
}
|
|
1470
|
-
function addRunway(decodeResult, value) {
|
|
1471
|
-
if (value.length === 8) {
|
|
1472
|
-
decodeResult.raw.arrival_runway = value.substring(4, 7);
|
|
1473
|
-
decodeResult.formatted.items.push({
|
|
1474
|
-
type: "runway",
|
|
1475
|
-
label: "Arrival Runway",
|
|
1476
|
-
value: decodeResult.raw.arrival_runway
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1479
|
-
decodeResult.raw.departure_runway = value.substring(0, 3);
|
|
1480
|
-
decodeResult.formatted.items.push({
|
|
1481
|
-
type: "runway",
|
|
1482
|
-
label: "Departure Runway",
|
|
1483
|
-
value: decodeResult.raw.departure_runway
|
|
1484
|
-
});
|
|
1675
|
+
ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
|
|
1485
1676
|
}
|
|
1486
1677
|
function addRoute(decodeResult, value) {
|
|
1487
1678
|
const route = value.split(".");
|
|
@@ -1541,6 +1732,286 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1541
1732
|
});
|
|
1542
1733
|
}
|
|
1543
1734
|
|
|
1735
|
+
// lib/utils/h1_helper.ts
|
|
1736
|
+
var H1Helper = class {
|
|
1737
|
+
static decodeH1Message(decodeResult, message) {
|
|
1738
|
+
let allKnownFields = true;
|
|
1739
|
+
const checksum = message.slice(-4);
|
|
1740
|
+
const data = message.slice(0, message.length - 4);
|
|
1741
|
+
const fields = data.split("/");
|
|
1742
|
+
allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
|
|
1743
|
+
for (let i = 1; i < fields.length; ++i) {
|
|
1744
|
+
if (fields[i].startsWith("FN")) {
|
|
1745
|
+
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
1746
|
+
} else if (fields[i].startsWith("SN")) {
|
|
1747
|
+
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
1748
|
+
} else if (fields[i].startsWith("DC")) {
|
|
1749
|
+
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
1750
|
+
} else if (fields[i].startsWith("TS")) {
|
|
1751
|
+
const ts = fields[i].substring(2).split(",");
|
|
1752
|
+
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
1753
|
+
if (Number.isNaN(time)) {
|
|
1754
|
+
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
1755
|
+
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
1756
|
+
}
|
|
1757
|
+
decodeResult.raw.message_date = ts[1];
|
|
1758
|
+
decodeResult.raw.message_timestamp = time;
|
|
1759
|
+
} else if (fields[i].startsWith("PS")) {
|
|
1760
|
+
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
1761
|
+
allKnownFields == allKnownFields && pos;
|
|
1762
|
+
} else if (fields[i].startsWith("DT")) {
|
|
1763
|
+
const data2 = fields[i].substring(2).split(",");
|
|
1764
|
+
const dt = processDT(decodeResult, data2);
|
|
1765
|
+
allKnownFields = allKnownFields && dt;
|
|
1766
|
+
} else if (fields[i].startsWith("ID")) {
|
|
1767
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
1768
|
+
} else if (fields[i].startsWith("LR")) {
|
|
1769
|
+
const data2 = fields[i].substring(2).split(",");
|
|
1770
|
+
const lr = processLR(decodeResult, data2);
|
|
1771
|
+
allKnownFields = allKnownFields && lr;
|
|
1772
|
+
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
1773
|
+
const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
1774
|
+
allKnownFields = allKnownFields && fp;
|
|
1775
|
+
} else if (fields[i].startsWith("PR")) {
|
|
1776
|
+
allKnownFields = false;
|
|
1777
|
+
decodeResult.remaining.text += "/" + fields[i];
|
|
1778
|
+
} else if (fields[i].startsWith("PS")) {
|
|
1779
|
+
allKnownFields = false;
|
|
1780
|
+
decodeResult.remaining.text += fields[i];
|
|
1781
|
+
} else if (fields[i].startsWith("AF")) {
|
|
1782
|
+
const af = processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
1783
|
+
allKnownFields = allKnownFields && af;
|
|
1784
|
+
} else if (fields[i].startsWith("TD")) {
|
|
1785
|
+
const td = processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
1786
|
+
allKnownFields = allKnownFields && td;
|
|
1787
|
+
} else if (fields[i].startsWith("FX")) {
|
|
1788
|
+
decodeResult.raw.free_text = fields[i].substring(2);
|
|
1789
|
+
decodeResult.formatted.items.push({
|
|
1790
|
+
type: "text",
|
|
1791
|
+
code: "TEXT",
|
|
1792
|
+
label: "Free Text",
|
|
1793
|
+
value: decodeResult.raw.free_text
|
|
1794
|
+
});
|
|
1795
|
+
} else {
|
|
1796
|
+
decodeResult.remaining.text += "/" + fields[i];
|
|
1797
|
+
allKnownFields = false;
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
if (decodeResult.formatted.items.length > 0) {
|
|
1801
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
1802
|
+
}
|
|
1803
|
+
return allKnownFields;
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
function processAirField(decodeResult, data) {
|
|
1807
|
+
if (data.length === 2) {
|
|
1808
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
1809
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
1810
|
+
return true;
|
|
1811
|
+
}
|
|
1812
|
+
decodeResult.remaining.text += "AF/" + data.join(",");
|
|
1813
|
+
return false;
|
|
1814
|
+
}
|
|
1815
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
1816
|
+
if (data.length === 2) {
|
|
1817
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
1818
|
+
decodeResult.formatted.items.push({
|
|
1819
|
+
type: "ptd",
|
|
1820
|
+
code: "ptd",
|
|
1821
|
+
label: "Planned Departure Time",
|
|
1822
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
1823
|
+
});
|
|
1824
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
1825
|
+
decodeResult.formatted.items.push({
|
|
1826
|
+
type: "etd",
|
|
1827
|
+
code: "etd",
|
|
1828
|
+
label: "Estimated Departure Time",
|
|
1829
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
1830
|
+
});
|
|
1831
|
+
return true;
|
|
1832
|
+
}
|
|
1833
|
+
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
function processIdentification(decodeResult, data) {
|
|
1837
|
+
decodeResult.raw.tail = data[0];
|
|
1838
|
+
decodeResult.formatted.items.push({
|
|
1839
|
+
type: "tail",
|
|
1840
|
+
code: "TAIL",
|
|
1841
|
+
label: "Tail",
|
|
1842
|
+
value: decodeResult.raw.tail
|
|
1843
|
+
});
|
|
1844
|
+
if (data.length > 1) {
|
|
1845
|
+
decodeResult.raw.flight_number = data[1];
|
|
1846
|
+
}
|
|
1847
|
+
if (data.length > 2) {
|
|
1848
|
+
decodeResult.raw.mission_number = data[2];
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
function processDT(decodeResult, data) {
|
|
1852
|
+
let allKnownFields = true;
|
|
1853
|
+
if (!decodeResult.raw.arrival_icao) {
|
|
1854
|
+
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
1855
|
+
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
1856
|
+
decodeResult.remaining.text += "/" + data;
|
|
1857
|
+
}
|
|
1858
|
+
if (data.length > 1) {
|
|
1859
|
+
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
1860
|
+
}
|
|
1861
|
+
if (data.length > 2) {
|
|
1862
|
+
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
1863
|
+
}
|
|
1864
|
+
if (data.length > 3) {
|
|
1865
|
+
ResultFormatter.eta(decodeResult, data[3]);
|
|
1866
|
+
}
|
|
1867
|
+
if (data.length > 4) {
|
|
1868
|
+
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
1869
|
+
}
|
|
1870
|
+
if (data.length > 5) {
|
|
1871
|
+
allKnownFields = false;
|
|
1872
|
+
decodeResult.remaining.text += "," + data.slice(5).join(",");
|
|
1873
|
+
}
|
|
1874
|
+
return allKnownFields;
|
|
1875
|
+
}
|
|
1876
|
+
function processLR(decodeResult, data) {
|
|
1877
|
+
let allKnownFields = true;
|
|
1878
|
+
if (data.length === 19) {
|
|
1879
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1880
|
+
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
1881
|
+
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
1882
|
+
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
1883
|
+
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
1884
|
+
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
1885
|
+
allKnownFields = false;
|
|
1886
|
+
} else {
|
|
1887
|
+
allKnownFields = false;
|
|
1888
|
+
}
|
|
1889
|
+
return allKnownFields;
|
|
1890
|
+
}
|
|
1891
|
+
function parseMessageType(decodeResult, messageType) {
|
|
1892
|
+
let decoded = true;
|
|
1893
|
+
const parts = messageType.split("#");
|
|
1894
|
+
if (parts.length == 1) {
|
|
1895
|
+
if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
|
|
1896
|
+
decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
1897
|
+
}
|
|
1898
|
+
return decoded;
|
|
1899
|
+
} else if (parts.length == 2) {
|
|
1900
|
+
if (parts[0].length > 0) {
|
|
1901
|
+
decodeResult.remaining.text += parts[0].substring(0, 3);
|
|
1902
|
+
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
1903
|
+
decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
|
|
1904
|
+
}
|
|
1905
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
|
|
1906
|
+
decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
1907
|
+
}
|
|
1908
|
+
decodeResult.raw.message_type = messageType;
|
|
1909
|
+
return decoded;
|
|
1910
|
+
}
|
|
1911
|
+
decodeResult.remaining.text += messageType;
|
|
1912
|
+
return false;
|
|
1913
|
+
}
|
|
1914
|
+
function processDC(decodeResult, data) {
|
|
1915
|
+
decodeResult.raw.message_date = data[0];
|
|
1916
|
+
if (data.length === 1) {
|
|
1917
|
+
} else if (data.length === 2) {
|
|
1918
|
+
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
1919
|
+
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
1920
|
+
decodeResult.raw.message_timestamp = time;
|
|
1921
|
+
} else {
|
|
1922
|
+
return false;
|
|
1923
|
+
}
|
|
1924
|
+
return true;
|
|
1925
|
+
}
|
|
1926
|
+
function processPS(decodeResult, data) {
|
|
1927
|
+
let allKnownFields = true;
|
|
1928
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1929
|
+
if (position) {
|
|
1930
|
+
decodeResult.raw.position = position;
|
|
1931
|
+
decodeResult.formatted.items.push({
|
|
1932
|
+
type: "aircraft_position",
|
|
1933
|
+
code: "POS",
|
|
1934
|
+
label: "Aircraft Position",
|
|
1935
|
+
value: CoordinateUtils.coordinateString(position)
|
|
1936
|
+
});
|
|
1937
|
+
} else {
|
|
1938
|
+
allKnownFields = false;
|
|
1939
|
+
}
|
|
1940
|
+
console.log("PS data.length: ", data.length);
|
|
1941
|
+
console.log("PS data: ", data);
|
|
1942
|
+
if (data.length === 9) {
|
|
1943
|
+
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
1944
|
+
ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
|
|
1945
|
+
ResultFormatter.temperature(decodeResult, data[6]);
|
|
1946
|
+
ResultFormatter.unknown(decodeResult, data[7]);
|
|
1947
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1948
|
+
}
|
|
1949
|
+
if (data.length === 14) {
|
|
1950
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
1951
|
+
processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
|
|
1952
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
1953
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
1954
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1955
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1956
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
1957
|
+
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
1958
|
+
}
|
|
1959
|
+
allKnownFields = false;
|
|
1960
|
+
return allKnownFields;
|
|
1961
|
+
}
|
|
1962
|
+
function processPosition2(decodeResult, data) {
|
|
1963
|
+
let allKnownFields = true;
|
|
1964
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1965
|
+
if (position) {
|
|
1966
|
+
decodeResult.raw.position = position;
|
|
1967
|
+
decodeResult.formatted.items.push({
|
|
1968
|
+
type: "aircraft_position",
|
|
1969
|
+
code: "POS",
|
|
1970
|
+
label: "Aircraft Position",
|
|
1971
|
+
value: CoordinateUtils.coordinateString(position)
|
|
1972
|
+
});
|
|
1973
|
+
} else {
|
|
1974
|
+
allKnownFields = false;
|
|
1975
|
+
}
|
|
1976
|
+
console.log("data.length: ", data.length);
|
|
1977
|
+
console.log("data: ", data);
|
|
1978
|
+
if (data.length >= 10) {
|
|
1979
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
1980
|
+
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
1981
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
1982
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1983
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
1984
|
+
}
|
|
1985
|
+
if (data.length >= 14) {
|
|
1986
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
1987
|
+
ResultFormatter.unknown(decodeResult, data[11]);
|
|
1988
|
+
ResultFormatter.unknown(decodeResult, data[12]);
|
|
1989
|
+
ResultFormatter.unknown(decodeResult, data[13]);
|
|
1990
|
+
}
|
|
1991
|
+
allKnownFields = false;
|
|
1992
|
+
return allKnownFields;
|
|
1993
|
+
}
|
|
1994
|
+
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
1995
|
+
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
1996
|
+
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
1997
|
+
const timeFormat = date ? "epoch" : "tod";
|
|
1998
|
+
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
1999
|
+
lastWaypoint.time = lastTime;
|
|
2000
|
+
lastWaypoint.timeFormat = timeFormat;
|
|
2001
|
+
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2002
|
+
nextWaypoint.time = nextTime;
|
|
2003
|
+
nextWaypoint.timeFormat = timeFormat;
|
|
2004
|
+
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2005
|
+
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2006
|
+
decodeResult.raw.route = { waypoints };
|
|
2007
|
+
decodeResult.formatted.items.push({
|
|
2008
|
+
type: "aircraft_route",
|
|
2009
|
+
code: "ROUTE",
|
|
2010
|
+
label: "Aircraft Route",
|
|
2011
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1544
2015
|
// lib/plugins/Label_H1_FPN.ts
|
|
1545
2016
|
var Label_H1_FPN = class extends DecoderPlugin {
|
|
1546
2017
|
name = "label-h1-fpn";
|
|
@@ -1555,15 +2026,73 @@ var Label_H1_FPN = class extends DecoderPlugin {
|
|
|
1555
2026
|
decodeResult.decoder.name = this.name;
|
|
1556
2027
|
decodeResult.formatted.description = "Flight Plan";
|
|
1557
2028
|
decodeResult.message = message;
|
|
2029
|
+
decodeResult.remaining.text = "";
|
|
1558
2030
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
1559
|
-
const
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
2031
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2032
|
+
decodeResult.decoded = true;
|
|
2033
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2034
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2035
|
+
if (options?.debug) {
|
|
2036
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2037
|
+
}
|
|
2038
|
+
decodeResult.remaining.text = message.text;
|
|
2039
|
+
decodeResult.decoded = false;
|
|
2040
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2041
|
+
}
|
|
2042
|
+
return decodeResult;
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
|
|
2046
|
+
// lib/plugins/Label_H1_FTX.ts
|
|
2047
|
+
var Label_H1_FTX = class extends DecoderPlugin {
|
|
2048
|
+
name = "label-h1-ftx";
|
|
2049
|
+
qualifiers() {
|
|
2050
|
+
return {
|
|
2051
|
+
labels: ["H1"],
|
|
2052
|
+
preambles: ["FTX", "- #MDFTX"]
|
|
2053
|
+
};
|
|
2054
|
+
}
|
|
2055
|
+
decode(message, options = {}) {
|
|
2056
|
+
let decodeResult = this.defaultResult();
|
|
2057
|
+
decodeResult.decoder.name = this.name;
|
|
2058
|
+
decodeResult.formatted.description = "Free Text";
|
|
2059
|
+
decodeResult.message = message;
|
|
2060
|
+
decodeResult.remaining.text = "";
|
|
2061
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2062
|
+
decodeResult.decoded = true;
|
|
2063
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2064
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2065
|
+
if (options?.debug) {
|
|
2066
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2067
|
+
}
|
|
2068
|
+
decodeResult.remaining.text = message.text;
|
|
2069
|
+
decodeResult.decoded = false;
|
|
2070
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2071
|
+
}
|
|
2072
|
+
return decodeResult;
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
2075
|
+
|
|
2076
|
+
// lib/plugins/Label_H1_INI.ts
|
|
2077
|
+
var Label_H1_INI = class extends DecoderPlugin {
|
|
2078
|
+
// eslint-disable-line camelcase
|
|
2079
|
+
name = "label-h1-ini";
|
|
2080
|
+
qualifiers() {
|
|
2081
|
+
return {
|
|
2082
|
+
labels: ["H1"],
|
|
2083
|
+
preambles: ["INI", "- #MDINI"]
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
decode(message, options = {}) {
|
|
2087
|
+
const decodeResult = this.defaultResult();
|
|
2088
|
+
decodeResult.decoder.name = this.name;
|
|
2089
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2090
|
+
decodeResult.message = message;
|
|
2091
|
+
decodeResult.remaining.text = "";
|
|
2092
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2093
|
+
decodeResult.decoded = true;
|
|
2094
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2095
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
1567
2096
|
if (options?.debug) {
|
|
1568
2097
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1569
2098
|
}
|
|
@@ -1574,15 +2103,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
|
|
|
1574
2103
|
return decodeResult;
|
|
1575
2104
|
}
|
|
1576
2105
|
};
|
|
1577
|
-
function addChecksum(decodeResult, value) {
|
|
1578
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1579
|
-
decodeResult.formatted.items.push({
|
|
1580
|
-
type: "message_checksum",
|
|
1581
|
-
code: "CHECKSUM",
|
|
1582
|
-
label: "Message Checksum",
|
|
1583
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1584
|
-
});
|
|
1585
|
-
}
|
|
1586
2106
|
|
|
1587
2107
|
// lib/plugins/Label_H1_OHMA.ts
|
|
1588
2108
|
var zlib = __toESM(require("minizlib"));
|
|
@@ -1608,13 +2128,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
1608
2128
|
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
1609
2129
|
const result = decompress.read();
|
|
1610
2130
|
const jsonText = result.toString();
|
|
1611
|
-
const json = JSON.parse(jsonText);
|
|
1612
2131
|
let formattedMsg;
|
|
1613
|
-
|
|
1614
|
-
|
|
2132
|
+
let jsonMessage;
|
|
2133
|
+
try {
|
|
2134
|
+
jsonMessage = JSON.parse(jsonText).message;
|
|
2135
|
+
} catch {
|
|
2136
|
+
jsonMessage = jsonText;
|
|
2137
|
+
}
|
|
2138
|
+
try {
|
|
2139
|
+
const ohmaMsg = JSON.parse(jsonMessage);
|
|
1615
2140
|
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
1616
|
-
}
|
|
1617
|
-
formattedMsg =
|
|
2141
|
+
} catch {
|
|
2142
|
+
formattedMsg = jsonMessage;
|
|
1618
2143
|
}
|
|
1619
2144
|
decodeResult.decoded = true;
|
|
1620
2145
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1653,225 +2178,20 @@ var Label_H1_POS = class extends DecoderPlugin {
|
|
|
1653
2178
|
decodeResult.formatted.description = "Position Report";
|
|
1654
2179
|
decodeResult.message = message;
|
|
1655
2180
|
decodeResult.remaining.text = "";
|
|
1656
|
-
const
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
if (decoded) {
|
|
1662
|
-
processChecksum(decodeResult, checksum);
|
|
1663
|
-
decodeResult.decoded = true;
|
|
1664
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
1665
|
-
} else if (decodeResult.remaining.text.length > 0) {
|
|
1666
|
-
processChecksum(decodeResult, checksum);
|
|
1667
|
-
decodeResult.decoded = true;
|
|
1668
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1669
|
-
} else {
|
|
1670
|
-
decodeResult.decoded = false;
|
|
1671
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1672
|
-
}
|
|
1673
|
-
} else if (parts.length === 10) {
|
|
1674
|
-
processAlt(decodeResult, parts[3]);
|
|
1675
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
|
|
1676
|
-
processTemp(decodeResult, parts[7]);
|
|
1677
|
-
processUnknown(decodeResult, parts[8]);
|
|
1678
|
-
processUnknown(decodeResult, parts[9]);
|
|
1679
|
-
processChecksum(decodeResult, checksum);
|
|
1680
|
-
decodeResult.decoded = true;
|
|
1681
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1682
|
-
} else if (parts.length === 11) {
|
|
1683
|
-
processAlt(decodeResult, parts[3]);
|
|
1684
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
|
|
1685
|
-
processTemp(decodeResult, parts[7]);
|
|
1686
|
-
processUnknown(decodeResult, parts[8]);
|
|
1687
|
-
processUnknown(decodeResult, parts[9]);
|
|
1688
|
-
processChecksum(decodeResult, checksum);
|
|
1689
|
-
decodeResult.decoded = true;
|
|
1690
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1691
|
-
} else if (parts.length === 12) {
|
|
1692
|
-
const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
|
|
1693
|
-
processUnknown(decodeResult, parts[3]);
|
|
1694
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
|
|
1695
|
-
processTemp(decodeResult, parts[7]);
|
|
1696
|
-
processUnknown(decodeResult, parts[8]);
|
|
1697
|
-
processUnknown(decodeResult, parts[9]);
|
|
1698
|
-
processUnknown(decodeResult, parts[10]);
|
|
1699
|
-
processChecksum(decodeResult, checksum);
|
|
1700
|
-
decodeResult.decoded = true;
|
|
1701
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1702
|
-
} else if (parts.length === 14) {
|
|
1703
|
-
processAlt(decodeResult, parts[3]);
|
|
1704
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
|
|
1705
|
-
processTemp(decodeResult, parts[7]);
|
|
1706
|
-
processUnknown(decodeResult, parts[8]);
|
|
1707
|
-
processUnknown(decodeResult, parts[9]);
|
|
1708
|
-
processGndspd(decodeResult, parts[10]);
|
|
1709
|
-
processUnknown(decodeResult, parts[11]);
|
|
1710
|
-
processUnknown(decodeResult, parts[12]);
|
|
1711
|
-
processUnknown(decodeResult, parts[13]);
|
|
1712
|
-
processChecksum(decodeResult, checksum);
|
|
1713
|
-
decodeResult.decoded = true;
|
|
1714
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1715
|
-
} else if (parts.length === 15) {
|
|
1716
|
-
decodeResult.raw.flight_number = parts[1];
|
|
1717
|
-
let date = void 0;
|
|
1718
|
-
if (parts[2].startsWith("/DC")) {
|
|
1719
|
-
date = parts[2].substring(3);
|
|
1720
|
-
} else {
|
|
1721
|
-
processUnknown(decodeResult, parts[2]);
|
|
1722
|
-
}
|
|
1723
|
-
processUnknown(decodeResult, parts[3]);
|
|
1724
|
-
const fields = parts[4].split("/");
|
|
1725
|
-
for (let i = 0; i < fields.length; ++i) {
|
|
1726
|
-
const field = fields[i];
|
|
1727
|
-
if (field.startsWith("PS")) {
|
|
1728
|
-
processPosition2(decodeResult, field.substring(2));
|
|
1729
|
-
} else {
|
|
1730
|
-
if (i === 0) {
|
|
1731
|
-
processUnknown(decodeResult, field);
|
|
1732
|
-
} else {
|
|
1733
|
-
processUnknown(decodeResult, "/" + field);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
|
|
1738
|
-
processAlt(decodeResult, parts[6]);
|
|
1739
|
-
processTemp(decodeResult, parts[10]);
|
|
1740
|
-
processUnknown(decodeResult, parts[11]);
|
|
1741
|
-
processUnknown(decodeResult, parts[12]);
|
|
1742
|
-
processUnknown(decodeResult, parts[13]);
|
|
1743
|
-
processUnknown(decodeResult, parts[14]);
|
|
1744
|
-
processChecksum(decodeResult, checksum);
|
|
1745
|
-
decodeResult.decoded = true;
|
|
1746
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1747
|
-
} else if (parts.length === 21) {
|
|
1748
|
-
processRunway(decodeResult, parts[1]);
|
|
1749
|
-
processUnknown(decodeResult, parts.slice(2, 11).join(","));
|
|
1750
|
-
processTemp(decodeResult, parts[11]);
|
|
1751
|
-
processUnknown(decodeResult, parts.slice(12, 20).join(","));
|
|
1752
|
-
FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
|
|
1753
|
-
processChecksum(decodeResult, checksum);
|
|
1754
|
-
decodeResult.decoded = true;
|
|
1755
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1756
|
-
} else if (parts.length === 32) {
|
|
1757
|
-
processRunway(decodeResult, parts[1]);
|
|
1758
|
-
const time = parts[2];
|
|
1759
|
-
processUnknown(decodeResult, parts[3]);
|
|
1760
|
-
const past = parts[4];
|
|
1761
|
-
processUnknown(decodeResult, parts[5]);
|
|
1762
|
-
const eta = parts[6];
|
|
1763
|
-
const next = parts[7];
|
|
1764
|
-
processUnknown(decodeResult, parts.slice(8, 14).join(","));
|
|
1765
|
-
processUnknown(decodeResult, parts[16]);
|
|
1766
|
-
processUnknown(decodeResult, parts[17]);
|
|
1767
|
-
processUnknown(decodeResult, parts[18]);
|
|
1768
|
-
processGndspd(decodeResult, parts[19]);
|
|
1769
|
-
processUnknown(decodeResult, parts[20]);
|
|
1770
|
-
processUnknown(decodeResult, parts[21]);
|
|
1771
|
-
processAlt(decodeResult, parts[22]);
|
|
1772
|
-
processUnknown(decodeResult, parts.slice(23, 31).join(","));
|
|
1773
|
-
const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
|
|
1774
|
-
processRoute(decodeResult, past, time, next, eta);
|
|
1775
|
-
decodeResult.decoded = true;
|
|
1776
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1777
|
-
} else {
|
|
1778
|
-
if (options.debug) {
|
|
2181
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2182
|
+
decodeResult.decoded = true;
|
|
2183
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2184
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2185
|
+
if (options?.debug) {
|
|
1779
2186
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1780
2187
|
}
|
|
1781
|
-
decodeResult.remaining.text
|
|
2188
|
+
decodeResult.remaining.text = message.text;
|
|
1782
2189
|
decodeResult.decoded = false;
|
|
1783
2190
|
decodeResult.decoder.decodeLevel = "none";
|
|
1784
2191
|
}
|
|
1785
2192
|
return decodeResult;
|
|
1786
2193
|
}
|
|
1787
2194
|
};
|
|
1788
|
-
function processUnknown(decodeResult, value) {
|
|
1789
|
-
decodeResult.remaining.text += "," + value;
|
|
1790
|
-
}
|
|
1791
|
-
function processPosition2(decodeResult, value) {
|
|
1792
|
-
const position = CoordinateUtils.decodeStringCoordinates(value);
|
|
1793
|
-
if (position) {
|
|
1794
|
-
decodeResult.raw.position = position;
|
|
1795
|
-
decodeResult.formatted.items.push({
|
|
1796
|
-
type: "aircraft_position",
|
|
1797
|
-
code: "POS",
|
|
1798
|
-
label: "Aircraft Position",
|
|
1799
|
-
value: CoordinateUtils.coordinateString(position)
|
|
1800
|
-
});
|
|
1801
|
-
}
|
|
1802
|
-
}
|
|
1803
|
-
function processAlt(decodeResult, value) {
|
|
1804
|
-
decodeResult.raw.altitude = Number(value) * 100;
|
|
1805
|
-
decodeResult.formatted.items.push({
|
|
1806
|
-
type: "altitude",
|
|
1807
|
-
code: "ALT",
|
|
1808
|
-
label: "Altitude",
|
|
1809
|
-
value: `${decodeResult.raw.altitude} feet`
|
|
1810
|
-
});
|
|
1811
|
-
}
|
|
1812
|
-
function processTemp(decodeResult, value) {
|
|
1813
|
-
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1814
|
-
decodeResult.formatted.items.push({
|
|
1815
|
-
type: "outside_air_temperature",
|
|
1816
|
-
code: "OATEMP",
|
|
1817
|
-
label: "Outside Air Temperature (C)",
|
|
1818
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1819
|
-
});
|
|
1820
|
-
}
|
|
1821
|
-
function processRunway(decodeResult, value) {
|
|
1822
|
-
decodeResult.raw.arrival_runway = value.replace("RW", "");
|
|
1823
|
-
decodeResult.formatted.items.push({
|
|
1824
|
-
type: "runway",
|
|
1825
|
-
label: "Arrival Runway",
|
|
1826
|
-
value: decodeResult.raw.arrival_runway
|
|
1827
|
-
});
|
|
1828
|
-
}
|
|
1829
|
-
function processGndspd(decodeResult, value) {
|
|
1830
|
-
decodeResult.raw.groundspeed = Number(value);
|
|
1831
|
-
decodeResult.formatted.items.push({
|
|
1832
|
-
type: "aircraft_groundspeed",
|
|
1833
|
-
code: "GSPD",
|
|
1834
|
-
label: "Aircraft Groundspeed",
|
|
1835
|
-
value: `${decodeResult.raw.groundspeed}`
|
|
1836
|
-
});
|
|
1837
|
-
}
|
|
1838
|
-
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
1839
|
-
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
1840
|
-
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
1841
|
-
const timeFormat = date ? "epoch" : "tod";
|
|
1842
|
-
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
1843
|
-
lastWaypoint.time = lastTime;
|
|
1844
|
-
lastWaypoint.timeFormat = timeFormat;
|
|
1845
|
-
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
1846
|
-
nextWaypoint.time = nextTime;
|
|
1847
|
-
nextWaypoint.timeFormat = timeFormat;
|
|
1848
|
-
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
1849
|
-
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
1850
|
-
decodeResult.raw.route = { waypoints };
|
|
1851
|
-
decodeResult.formatted.items.push({
|
|
1852
|
-
type: "aircraft_route",
|
|
1853
|
-
code: "ROUTE",
|
|
1854
|
-
label: "Aircraft Route",
|
|
1855
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1856
|
-
});
|
|
1857
|
-
}
|
|
1858
|
-
function processChecksum(decodeResult, value) {
|
|
1859
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1860
|
-
decodeResult.formatted.items.push({
|
|
1861
|
-
type: "message_checksum",
|
|
1862
|
-
code: "CHECKSUM",
|
|
1863
|
-
label: "Message Checksum",
|
|
1864
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1865
|
-
});
|
|
1866
|
-
}
|
|
1867
|
-
function findHeader(text) {
|
|
1868
|
-
const parts = text.split(",");
|
|
1869
|
-
const header = parts[0];
|
|
1870
|
-
if (header.indexOf("/TS") === -1) {
|
|
1871
|
-
return header;
|
|
1872
|
-
}
|
|
1873
|
-
return parts[0] + "," + parts[1];
|
|
1874
|
-
}
|
|
1875
2195
|
|
|
1876
2196
|
// lib/plugins/Label_H1_WRN.ts
|
|
1877
2197
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
@@ -3026,6 +3346,7 @@ var MessageDecoder = class {
|
|
|
3026
3346
|
this.registerPlugin(new Label_15_FST(this));
|
|
3027
3347
|
this.registerPlugin(new Label_16_N_Space(this));
|
|
3028
3348
|
this.registerPlugin(new Label_20_POS(this));
|
|
3349
|
+
this.registerPlugin(new Label_21_POS(this));
|
|
3029
3350
|
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
3030
3351
|
this.registerPlugin(new Label_44_ETA(this));
|
|
3031
3352
|
this.registerPlugin(new Label_44_IN(this));
|
|
@@ -3034,6 +3355,9 @@ var MessageDecoder = class {
|
|
|
3034
3355
|
this.registerPlugin(new Label_44_POS(this));
|
|
3035
3356
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
3036
3357
|
this.registerPlugin(new Label_H1_FPN(this));
|
|
3358
|
+
this.registerPlugin(new Label_H1_FLR(this));
|
|
3359
|
+
this.registerPlugin(new Label_H1_FTX(this));
|
|
3360
|
+
this.registerPlugin(new Label_H1_INI(this));
|
|
3037
3361
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
3038
3362
|
this.registerPlugin(new Label_H1_POS(this));
|
|
3039
3363
|
this.registerPlugin(new Label_H1_WRN(this));
|