@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.mjs
CHANGED
|
@@ -171,6 +171,12 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
171
171
|
|
|
172
172
|
// lib/utils/coordinate_utils.ts
|
|
173
173
|
var CoordinateUtils = class {
|
|
174
|
+
/**
|
|
175
|
+
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
176
|
+
* @param stringCoords - The string of coordinates to decode
|
|
177
|
+
*
|
|
178
|
+
* @returns An object with latitude and longitude properties
|
|
179
|
+
*/
|
|
174
180
|
static decodeStringCoordinates(stringCoords) {
|
|
175
181
|
var results = {};
|
|
176
182
|
const firstChar = stringCoords.substring(0, 1);
|
|
@@ -188,6 +194,33 @@ var CoordinateUtils = class {
|
|
|
188
194
|
}
|
|
189
195
|
return results;
|
|
190
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
|
|
199
|
+
* @param stringCoords - The string of coordinates to decode
|
|
200
|
+
*
|
|
201
|
+
* @returns An object with latitude and longitude properties
|
|
202
|
+
*/
|
|
203
|
+
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
204
|
+
var results = {};
|
|
205
|
+
const firstChar = stringCoords.substring(0, 1);
|
|
206
|
+
let middleChar = stringCoords.substring(6, 7);
|
|
207
|
+
let longitudeChars = stringCoords.substring(7, 13);
|
|
208
|
+
if (middleChar == " ") {
|
|
209
|
+
middleChar = stringCoords.substring(7, 8);
|
|
210
|
+
longitudeChars = stringCoords.substring(8, 14);
|
|
211
|
+
}
|
|
212
|
+
const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
|
|
213
|
+
const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
|
|
214
|
+
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
215
|
+
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
216
|
+
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
217
|
+
results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
|
|
218
|
+
results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
|
|
219
|
+
} else {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
return results;
|
|
223
|
+
}
|
|
191
224
|
static coordinateString(coords) {
|
|
192
225
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
193
226
|
const lonDir = coords.longitude > 0 ? "E" : "W";
|
|
@@ -558,6 +591,96 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
558
591
|
}
|
|
559
592
|
};
|
|
560
593
|
|
|
594
|
+
// lib/plugins/Label_21_POS.ts
|
|
595
|
+
var Label_21_POS = class extends DecoderPlugin {
|
|
596
|
+
name = "label-21-pos";
|
|
597
|
+
qualifiers() {
|
|
598
|
+
return {
|
|
599
|
+
labels: ["21"],
|
|
600
|
+
preambles: ["POS"]
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
decode(message, options = {}) {
|
|
604
|
+
const decodeResult = this.defaultResult();
|
|
605
|
+
decodeResult.decoder.name = this.name;
|
|
606
|
+
decodeResult.formatted.description = "Position Report";
|
|
607
|
+
decodeResult.message = message;
|
|
608
|
+
decodeResult.raw.preamble = message.text.substring(0, 3);
|
|
609
|
+
const content = message.text.substring(3);
|
|
610
|
+
console.log("Content: " + content);
|
|
611
|
+
const fields = content.split(",");
|
|
612
|
+
console.log("Field Count: " + fields.length);
|
|
613
|
+
if (fields.length == 9) {
|
|
614
|
+
processPosition(decodeResult, fields[0].trim());
|
|
615
|
+
processAlt(decodeResult, fields[3]);
|
|
616
|
+
processTemp(decodeResult, fields[6]);
|
|
617
|
+
processArrvApt(decodeResult, fields[8]);
|
|
618
|
+
decodeResult.raw.remaining = [
|
|
619
|
+
fields[1],
|
|
620
|
+
fields[2],
|
|
621
|
+
fields[4],
|
|
622
|
+
fields[5],
|
|
623
|
+
fields[7]
|
|
624
|
+
].join(",");
|
|
625
|
+
decodeResult.decoded = true;
|
|
626
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
627
|
+
} else {
|
|
628
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
|
|
629
|
+
decodeResult.decoded = false;
|
|
630
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
631
|
+
}
|
|
632
|
+
return decodeResult;
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
function processPosition(decodeResult, value) {
|
|
636
|
+
if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
const latDir = value[0] === "N" ? 1 : -1;
|
|
640
|
+
const lonDir = value[8] === "E" ? 1 : -1;
|
|
641
|
+
const position = {
|
|
642
|
+
latitude: latDir * Number(value.substring(1, 7)),
|
|
643
|
+
longitude: lonDir * Number(value.substring(9, 15))
|
|
644
|
+
};
|
|
645
|
+
if (position) {
|
|
646
|
+
decodeResult.raw.position = position;
|
|
647
|
+
decodeResult.formatted.items.push({
|
|
648
|
+
type: "aircraft_position",
|
|
649
|
+
code: "POS",
|
|
650
|
+
label: "Aircraft Position",
|
|
651
|
+
value: CoordinateUtils.coordinateString(position)
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
return !!position;
|
|
655
|
+
}
|
|
656
|
+
function processAlt(decodeResult, value) {
|
|
657
|
+
decodeResult.raw.altitude = Number(value);
|
|
658
|
+
decodeResult.formatted.items.push({
|
|
659
|
+
type: "altitude",
|
|
660
|
+
code: "ALT",
|
|
661
|
+
label: "Altitude",
|
|
662
|
+
value: `${decodeResult.raw.altitude} feet`
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
function processTemp(decodeResult, value) {
|
|
666
|
+
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
667
|
+
decodeResult.formatted.items.push({
|
|
668
|
+
type: "outside_air_temperature",
|
|
669
|
+
code: "OATEMP",
|
|
670
|
+
label: "Outside Air Temperature (C)",
|
|
671
|
+
value: `${decodeResult.raw.outside_air_temperature}`
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
function processArrvApt(decodeResult, value) {
|
|
675
|
+
decodeResult.raw.arrival_icao = value;
|
|
676
|
+
decodeResult.formatted.items.push({
|
|
677
|
+
type: "destination",
|
|
678
|
+
code: "DST",
|
|
679
|
+
label: "Destination",
|
|
680
|
+
value: decodeResult.raw.arrival_icao
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
561
684
|
// lib/plugins/Label_30_Slash_EA.ts
|
|
562
685
|
var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
563
686
|
name = "label-30-slash-ea";
|
|
@@ -855,7 +978,7 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
855
978
|
console.log(`Label 44 Position Report: groups`);
|
|
856
979
|
console.log(results.groups);
|
|
857
980
|
}
|
|
858
|
-
decodeResult.raw.position = CoordinateUtils.
|
|
981
|
+
decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
|
|
859
982
|
decodeResult.raw.flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? "0" : Number(results.groups.flight_level_or_ground);
|
|
860
983
|
decodeResult.raw.departure_icao = results.groups.departure_icao;
|
|
861
984
|
decodeResult.raw.arrival_icao = results.groups.arrival_icao;
|
|
@@ -870,9 +993,9 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
870
993
|
}
|
|
871
994
|
if (decodeResult.raw.position) {
|
|
872
995
|
decodeResult.formatted.items.push({
|
|
873
|
-
type: "
|
|
996
|
+
type: "aircraft_position",
|
|
874
997
|
code: "POS",
|
|
875
|
-
label: "Position",
|
|
998
|
+
label: "Aircraft Position",
|
|
876
999
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
877
1000
|
});
|
|
878
1001
|
}
|
|
@@ -1180,6 +1303,168 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
1180
1303
|
}
|
|
1181
1304
|
};
|
|
1182
1305
|
|
|
1306
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
1307
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
1308
|
+
name = "label-h1-flr";
|
|
1309
|
+
qualifiers() {
|
|
1310
|
+
return {
|
|
1311
|
+
labels: ["H1"],
|
|
1312
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
decode(message, options = {}) {
|
|
1316
|
+
let decodeResult = this.defaultResult();
|
|
1317
|
+
decodeResult.decoder.name = this.name;
|
|
1318
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
1319
|
+
decodeResult.message = message;
|
|
1320
|
+
const parts = message.text.split("/FR");
|
|
1321
|
+
if (parts.length > 1) {
|
|
1322
|
+
decodeResult.remaining.text = "";
|
|
1323
|
+
const fields = parts[0].split("/");
|
|
1324
|
+
for (let i = 1; i < fields.length; i++) {
|
|
1325
|
+
const field = fields[i];
|
|
1326
|
+
if (field.startsWith("PN")) {
|
|
1327
|
+
processUnknown(decodeResult, "/" + field);
|
|
1328
|
+
} else {
|
|
1329
|
+
processUnknown(decodeResult, "/" + field);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
const data = parts[1].substring(0, 20);
|
|
1333
|
+
const msg = parts[1].substring(20);
|
|
1334
|
+
const datetime = data.substring(0, 12);
|
|
1335
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
1336
|
+
processUnknown(decodeResult, data.substring(12));
|
|
1337
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
1338
|
+
decodeResult.raw.fault_message = msg;
|
|
1339
|
+
decodeResult.formatted.items.push({
|
|
1340
|
+
type: "fault",
|
|
1341
|
+
code: "FR",
|
|
1342
|
+
label: "Fault Report",
|
|
1343
|
+
value: decodeResult.raw.fault_message
|
|
1344
|
+
});
|
|
1345
|
+
decodeResult.decoded = true;
|
|
1346
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1347
|
+
} else {
|
|
1348
|
+
if (options.debug) {
|
|
1349
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1350
|
+
}
|
|
1351
|
+
decodeResult.remaining.text = message.text;
|
|
1352
|
+
decodeResult.decoded = false;
|
|
1353
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1354
|
+
}
|
|
1355
|
+
return decodeResult;
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
function processUnknown(decodeResult, value) {
|
|
1359
|
+
decodeResult.remaining.text += value;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// lib/utils/result_formatter.ts
|
|
1363
|
+
var ResultFormatter = class {
|
|
1364
|
+
static altitude(decodeResult, value) {
|
|
1365
|
+
decodeResult.raw.altitude = value;
|
|
1366
|
+
decodeResult.formatted.items.push({
|
|
1367
|
+
type: "altitude",
|
|
1368
|
+
code: "ALT",
|
|
1369
|
+
label: "Altitude",
|
|
1370
|
+
value: `${decodeResult.raw.altitude} feet`
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
static flightNumber(decodeResult, value) {
|
|
1374
|
+
decodeResult.raw.flight_number = value;
|
|
1375
|
+
}
|
|
1376
|
+
static departureAirport(decodeResult, value) {
|
|
1377
|
+
decodeResult.raw.departure_icao = value;
|
|
1378
|
+
decodeResult.formatted.items.push({
|
|
1379
|
+
type: "origin",
|
|
1380
|
+
code: "ORG",
|
|
1381
|
+
label: "Origin",
|
|
1382
|
+
value: decodeResult.raw.departure_icao
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
static departureRunway(decodeResult, value) {
|
|
1386
|
+
decodeResult.raw.departure_runway = value;
|
|
1387
|
+
decodeResult.formatted.items.push({
|
|
1388
|
+
type: "runway",
|
|
1389
|
+
code: "DEPRWY",
|
|
1390
|
+
label: "Departure Runway",
|
|
1391
|
+
value: decodeResult.raw.departure_runway
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
static arrivalAirport(decodeResult, value) {
|
|
1395
|
+
decodeResult.raw.arrival_icao = value;
|
|
1396
|
+
decodeResult.formatted.items.push({
|
|
1397
|
+
type: "destination",
|
|
1398
|
+
code: "DST",
|
|
1399
|
+
label: "Destination",
|
|
1400
|
+
value: decodeResult.raw.arrival_icao
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
static eta(decodeResult, value) {
|
|
1404
|
+
decodeResult.formatted.items.push({
|
|
1405
|
+
type: "eta",
|
|
1406
|
+
code: "ETA",
|
|
1407
|
+
label: "Estimated Time of Arrival",
|
|
1408
|
+
value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
static arrivalRunway(decodeResult, value) {
|
|
1412
|
+
decodeResult.raw.arrival_runway = value;
|
|
1413
|
+
decodeResult.formatted.items.push({
|
|
1414
|
+
type: "runway",
|
|
1415
|
+
label: "Arrival Runway",
|
|
1416
|
+
value: decodeResult.raw.arrival_runway
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
static currentFuel(decodeResult, value) {
|
|
1420
|
+
decodeResult.raw.fuel_on_board = value;
|
|
1421
|
+
decodeResult.formatted.items.push({
|
|
1422
|
+
type: "fuel_on_board",
|
|
1423
|
+
code: "FOB",
|
|
1424
|
+
label: "Fuel On Board",
|
|
1425
|
+
value: decodeResult.raw.fuel_on_board.toString()
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
static remainingFuel(decodeResult, value) {
|
|
1429
|
+
decodeResult.raw.fuel_remaining = value;
|
|
1430
|
+
decodeResult.formatted.items.push({
|
|
1431
|
+
type: "fuel_remaining",
|
|
1432
|
+
label: "Fuel Remaining",
|
|
1433
|
+
value: decodeResult.raw.fuel_remaining.toString()
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
static checksum(decodeResult, value) {
|
|
1437
|
+
decodeResult.raw.checksum = Number("0x" + value);
|
|
1438
|
+
decodeResult.formatted.items.push({
|
|
1439
|
+
type: "message_checksum",
|
|
1440
|
+
code: "CHECKSUM",
|
|
1441
|
+
label: "Message Checksum",
|
|
1442
|
+
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
static groundspeed(decodeResult, value) {
|
|
1446
|
+
decodeResult.raw.groundspeed = value;
|
|
1447
|
+
decodeResult.formatted.items.push({
|
|
1448
|
+
type: "aircraft_groundspeed",
|
|
1449
|
+
code: "GSPD",
|
|
1450
|
+
label: "Aircraft Groundspeed",
|
|
1451
|
+
value: `${decodeResult.raw.groundspeed}`
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
static temperature(decodeResult, value) {
|
|
1455
|
+
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1456
|
+
decodeResult.formatted.items.push({
|
|
1457
|
+
type: "outside_air_temperature",
|
|
1458
|
+
code: "OATEMP",
|
|
1459
|
+
label: "Outside Air Temperature (C)",
|
|
1460
|
+
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
static unknown(decodeResult, value) {
|
|
1464
|
+
decodeResult.remaining.text += "," + value;
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1183
1468
|
// lib/utils/route_utils.ts
|
|
1184
1469
|
var RouteUtils = class _RouteUtils {
|
|
1185
1470
|
static routeToString(route) {
|
|
@@ -1220,13 +1505,13 @@ var RouteUtils = class _RouteUtils {
|
|
|
1220
1505
|
}
|
|
1221
1506
|
const waypoint = leg.split(",");
|
|
1222
1507
|
if (waypoint.length == 2) {
|
|
1223
|
-
const position = CoordinateUtils.
|
|
1508
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
1224
1509
|
if (position) {
|
|
1225
1510
|
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
1226
1511
|
}
|
|
1227
1512
|
}
|
|
1228
1513
|
if (leg.length == 13 || leg.length == 14) {
|
|
1229
|
-
const position = CoordinateUtils.
|
|
1514
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
1230
1515
|
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
1231
1516
|
if (position) {
|
|
1232
1517
|
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
@@ -1305,146 +1590,52 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1305
1590
|
}
|
|
1306
1591
|
static parseHeader(decodeResult, header) {
|
|
1307
1592
|
let allKnownFields = true;
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
if (Number.isNaN(time)) {
|
|
1319
|
-
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
1320
|
-
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
1321
|
-
}
|
|
1322
|
-
decodeResult.raw.message_timestamp = time;
|
|
1323
|
-
} else if (fields[i].startsWith("PS")) {
|
|
1324
|
-
const pos = fields[i].substring(2);
|
|
1325
|
-
allKnownFields == allKnownFields && processPosition(decodeResult, pos);
|
|
1326
|
-
} else if (fields[i].startsWith("DT")) {
|
|
1327
|
-
const icao = fields[i].substring(2);
|
|
1328
|
-
decodeResult.raw.arrival_icao = icao;
|
|
1329
|
-
decodeResult.formatted.items.push({
|
|
1330
|
-
type: "destination",
|
|
1331
|
-
code: "DST",
|
|
1332
|
-
label: "Destination",
|
|
1333
|
-
value: decodeResult.raw.arrival_icao
|
|
1334
|
-
});
|
|
1335
|
-
} else if (fields[i].startsWith("ID")) {
|
|
1336
|
-
const tail = fields[i].substring(2);
|
|
1337
|
-
decodeResult.raw.tail = tail;
|
|
1338
|
-
decodeResult.formatted.items.push({
|
|
1339
|
-
type: "tail",
|
|
1340
|
-
label: "Tail",
|
|
1341
|
-
value: decodeResult.raw.tail
|
|
1342
|
-
});
|
|
1343
|
-
} else if (fields[i].startsWith("RF")) {
|
|
1344
|
-
decodeResult.formatted.items.push({
|
|
1345
|
-
type: "status",
|
|
1346
|
-
code: "ROUTE_STATUS",
|
|
1347
|
-
label: "Route Status",
|
|
1348
|
-
value: "Route Filed"
|
|
1349
|
-
});
|
|
1350
|
-
decodeResult.raw.route_status = "RF";
|
|
1351
|
-
if (fields[i].length > 2) {
|
|
1352
|
-
addRoute(decodeResult, fields[i].substring(2));
|
|
1353
|
-
}
|
|
1354
|
-
} else if (fields[i] == "RP") {
|
|
1355
|
-
decodeResult.raw.route_status = "RP";
|
|
1356
|
-
decodeResult.formatted.items.push({
|
|
1357
|
-
type: "status",
|
|
1358
|
-
code: "ROUTE_STATUS",
|
|
1359
|
-
label: "Route Status",
|
|
1360
|
-
value: "Route Planned"
|
|
1361
|
-
});
|
|
1362
|
-
decodeResult.raw.route_status = fields[i];
|
|
1363
|
-
} else if (fields[i] == "RI") {
|
|
1364
|
-
decodeResult.raw.route_status = "RI";
|
|
1365
|
-
decodeResult.formatted.items.push({
|
|
1366
|
-
type: "status",
|
|
1367
|
-
code: "ROUTE_STATUS",
|
|
1368
|
-
label: "Route Status",
|
|
1369
|
-
value: "Route Inactive"
|
|
1370
|
-
});
|
|
1371
|
-
} else {
|
|
1372
|
-
decodeResult.remaining.text += "/" + fields[i];
|
|
1373
|
-
allKnownFields = false;
|
|
1593
|
+
if (header.startsWith("RF")) {
|
|
1594
|
+
decodeResult.formatted.items.push({
|
|
1595
|
+
type: "status",
|
|
1596
|
+
code: "ROUTE_STATUS",
|
|
1597
|
+
label: "Route Status",
|
|
1598
|
+
value: "Route Filed"
|
|
1599
|
+
});
|
|
1600
|
+
decodeResult.raw.route_status = "RF";
|
|
1601
|
+
if (header.length > 2) {
|
|
1602
|
+
addRoute(decodeResult, header.substring(2));
|
|
1374
1603
|
}
|
|
1604
|
+
} else if (header.startsWith("RP")) {
|
|
1605
|
+
decodeResult.raw.route_status = "RP";
|
|
1606
|
+
decodeResult.formatted.items.push({
|
|
1607
|
+
type: "status",
|
|
1608
|
+
code: "ROUTE_STATUS",
|
|
1609
|
+
label: "Route Status",
|
|
1610
|
+
value: "Route Planned"
|
|
1611
|
+
});
|
|
1612
|
+
decodeResult.raw.route_status = header;
|
|
1613
|
+
} else if (header.startsWith("RI")) {
|
|
1614
|
+
decodeResult.raw.route_status = "RI";
|
|
1615
|
+
decodeResult.formatted.items.push({
|
|
1616
|
+
type: "status",
|
|
1617
|
+
code: "ROUTE_STATUS",
|
|
1618
|
+
label: "Route Status",
|
|
1619
|
+
value: "Route Inactive"
|
|
1620
|
+
});
|
|
1621
|
+
} else {
|
|
1622
|
+
decodeResult.remaining.text += header;
|
|
1623
|
+
allKnownFields = false;
|
|
1375
1624
|
}
|
|
1376
1625
|
return allKnownFields;
|
|
1377
1626
|
}
|
|
1378
1627
|
};
|
|
1379
|
-
function
|
|
1380
|
-
|
|
1381
|
-
const parts = messageType.split("#");
|
|
1382
|
-
if (parts.length == 1) {
|
|
1383
|
-
if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
|
|
1384
|
-
decoded = processPosition(decodeResult, parts[0].substring(3));
|
|
1385
|
-
}
|
|
1386
|
-
return decoded;
|
|
1387
|
-
} else if (parts.length == 2) {
|
|
1388
|
-
if (parts[0].length > 0) {
|
|
1389
|
-
decodeResult.remaining.text += parts[0].substring(0, 3);
|
|
1390
|
-
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
1391
|
-
decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
|
|
1392
|
-
}
|
|
1393
|
-
if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
|
|
1394
|
-
decoded = processPosition(decodeResult, parts[1].substring(6));
|
|
1395
|
-
}
|
|
1396
|
-
decodeResult.raw.message_type = messageType;
|
|
1397
|
-
return decoded;
|
|
1398
|
-
}
|
|
1399
|
-
decodeResult.remaining.text += messageType;
|
|
1400
|
-
return false;
|
|
1628
|
+
function addArrivalAirport(decodeResult, value) {
|
|
1629
|
+
ResultFormatter.arrivalAirport(decodeResult, value);
|
|
1401
1630
|
}
|
|
1402
|
-
function
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
code: "POS",
|
|
1409
|
-
label: "Aircraft Position",
|
|
1410
|
-
value: CoordinateUtils.coordinateString(position)
|
|
1411
|
-
});
|
|
1631
|
+
function addDepartureAirport(decodeResult, value) {
|
|
1632
|
+
ResultFormatter.departureAirport(decodeResult, value);
|
|
1633
|
+
}
|
|
1634
|
+
function addRunway(decodeResult, value) {
|
|
1635
|
+
if (value.length === 8) {
|
|
1636
|
+
ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
|
|
1412
1637
|
}
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1415
|
-
function addArrivalAirport(decodeResult, value) {
|
|
1416
|
-
decodeResult.raw.arrival_icao = value;
|
|
1417
|
-
decodeResult.formatted.items.push({
|
|
1418
|
-
type: "destination",
|
|
1419
|
-
code: "DST",
|
|
1420
|
-
label: "Destination",
|
|
1421
|
-
value: decodeResult.raw.arrival_icao
|
|
1422
|
-
});
|
|
1423
|
-
}
|
|
1424
|
-
function addDepartureAirport(decodeResult, value) {
|
|
1425
|
-
decodeResult.raw.departure_icao = value;
|
|
1426
|
-
decodeResult.formatted.items.push({
|
|
1427
|
-
type: "origin",
|
|
1428
|
-
code: "ORG",
|
|
1429
|
-
label: "Origin",
|
|
1430
|
-
value: decodeResult.raw.departure_icao
|
|
1431
|
-
});
|
|
1432
|
-
}
|
|
1433
|
-
function addRunway(decodeResult, value) {
|
|
1434
|
-
if (value.length === 8) {
|
|
1435
|
-
decodeResult.raw.arrival_runway = value.substring(4, 7);
|
|
1436
|
-
decodeResult.formatted.items.push({
|
|
1437
|
-
type: "runway",
|
|
1438
|
-
label: "Arrival Runway",
|
|
1439
|
-
value: decodeResult.raw.arrival_runway
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
decodeResult.raw.departure_runway = value.substring(0, 3);
|
|
1443
|
-
decodeResult.formatted.items.push({
|
|
1444
|
-
type: "runway",
|
|
1445
|
-
label: "Departure Runway",
|
|
1446
|
-
value: decodeResult.raw.departure_runway
|
|
1447
|
-
});
|
|
1638
|
+
ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
|
|
1448
1639
|
}
|
|
1449
1640
|
function addRoute(decodeResult, value) {
|
|
1450
1641
|
const route = value.split(".");
|
|
@@ -1504,6 +1695,286 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1504
1695
|
});
|
|
1505
1696
|
}
|
|
1506
1697
|
|
|
1698
|
+
// lib/utils/h1_helper.ts
|
|
1699
|
+
var H1Helper = class {
|
|
1700
|
+
static decodeH1Message(decodeResult, message) {
|
|
1701
|
+
let allKnownFields = true;
|
|
1702
|
+
const checksum = message.slice(-4);
|
|
1703
|
+
const data = message.slice(0, message.length - 4);
|
|
1704
|
+
const fields = data.split("/");
|
|
1705
|
+
allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
|
|
1706
|
+
for (let i = 1; i < fields.length; ++i) {
|
|
1707
|
+
if (fields[i].startsWith("FN")) {
|
|
1708
|
+
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
1709
|
+
} else if (fields[i].startsWith("SN")) {
|
|
1710
|
+
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
1711
|
+
} else if (fields[i].startsWith("DC")) {
|
|
1712
|
+
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
1713
|
+
} else if (fields[i].startsWith("TS")) {
|
|
1714
|
+
const ts = fields[i].substring(2).split(",");
|
|
1715
|
+
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
1716
|
+
if (Number.isNaN(time)) {
|
|
1717
|
+
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
1718
|
+
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
1719
|
+
}
|
|
1720
|
+
decodeResult.raw.message_date = ts[1];
|
|
1721
|
+
decodeResult.raw.message_timestamp = time;
|
|
1722
|
+
} else if (fields[i].startsWith("PS")) {
|
|
1723
|
+
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
1724
|
+
allKnownFields == allKnownFields && pos;
|
|
1725
|
+
} else if (fields[i].startsWith("DT")) {
|
|
1726
|
+
const data2 = fields[i].substring(2).split(",");
|
|
1727
|
+
const dt = processDT(decodeResult, data2);
|
|
1728
|
+
allKnownFields = allKnownFields && dt;
|
|
1729
|
+
} else if (fields[i].startsWith("ID")) {
|
|
1730
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
1731
|
+
} else if (fields[i].startsWith("LR")) {
|
|
1732
|
+
const data2 = fields[i].substring(2).split(",");
|
|
1733
|
+
const lr = processLR(decodeResult, data2);
|
|
1734
|
+
allKnownFields = allKnownFields && lr;
|
|
1735
|
+
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
1736
|
+
const fp = FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
1737
|
+
allKnownFields = allKnownFields && fp;
|
|
1738
|
+
} else if (fields[i].startsWith("PR")) {
|
|
1739
|
+
allKnownFields = false;
|
|
1740
|
+
decodeResult.remaining.text += "/" + fields[i];
|
|
1741
|
+
} else if (fields[i].startsWith("PS")) {
|
|
1742
|
+
allKnownFields = false;
|
|
1743
|
+
decodeResult.remaining.text += fields[i];
|
|
1744
|
+
} else if (fields[i].startsWith("AF")) {
|
|
1745
|
+
const af = processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
1746
|
+
allKnownFields = allKnownFields && af;
|
|
1747
|
+
} else if (fields[i].startsWith("TD")) {
|
|
1748
|
+
const td = processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
1749
|
+
allKnownFields = allKnownFields && td;
|
|
1750
|
+
} else if (fields[i].startsWith("FX")) {
|
|
1751
|
+
decodeResult.raw.free_text = fields[i].substring(2);
|
|
1752
|
+
decodeResult.formatted.items.push({
|
|
1753
|
+
type: "text",
|
|
1754
|
+
code: "TEXT",
|
|
1755
|
+
label: "Free Text",
|
|
1756
|
+
value: decodeResult.raw.free_text
|
|
1757
|
+
});
|
|
1758
|
+
} else {
|
|
1759
|
+
decodeResult.remaining.text += "/" + fields[i];
|
|
1760
|
+
allKnownFields = false;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
if (decodeResult.formatted.items.length > 0) {
|
|
1764
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
1765
|
+
}
|
|
1766
|
+
return allKnownFields;
|
|
1767
|
+
}
|
|
1768
|
+
};
|
|
1769
|
+
function processAirField(decodeResult, data) {
|
|
1770
|
+
if (data.length === 2) {
|
|
1771
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
1772
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
1773
|
+
return true;
|
|
1774
|
+
}
|
|
1775
|
+
decodeResult.remaining.text += "AF/" + data.join(",");
|
|
1776
|
+
return false;
|
|
1777
|
+
}
|
|
1778
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
1779
|
+
if (data.length === 2) {
|
|
1780
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
1781
|
+
decodeResult.formatted.items.push({
|
|
1782
|
+
type: "ptd",
|
|
1783
|
+
code: "ptd",
|
|
1784
|
+
label: "Planned Departure Time",
|
|
1785
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
1786
|
+
});
|
|
1787
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
1788
|
+
decodeResult.formatted.items.push({
|
|
1789
|
+
type: "etd",
|
|
1790
|
+
code: "etd",
|
|
1791
|
+
label: "Estimated Departure Time",
|
|
1792
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
1793
|
+
});
|
|
1794
|
+
return true;
|
|
1795
|
+
}
|
|
1796
|
+
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
1797
|
+
return false;
|
|
1798
|
+
}
|
|
1799
|
+
function processIdentification(decodeResult, data) {
|
|
1800
|
+
decodeResult.raw.tail = data[0];
|
|
1801
|
+
decodeResult.formatted.items.push({
|
|
1802
|
+
type: "tail",
|
|
1803
|
+
code: "TAIL",
|
|
1804
|
+
label: "Tail",
|
|
1805
|
+
value: decodeResult.raw.tail
|
|
1806
|
+
});
|
|
1807
|
+
if (data.length > 1) {
|
|
1808
|
+
decodeResult.raw.flight_number = data[1];
|
|
1809
|
+
}
|
|
1810
|
+
if (data.length > 2) {
|
|
1811
|
+
decodeResult.raw.mission_number = data[2];
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
function processDT(decodeResult, data) {
|
|
1815
|
+
let allKnownFields = true;
|
|
1816
|
+
if (!decodeResult.raw.arrival_icao) {
|
|
1817
|
+
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
1818
|
+
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
1819
|
+
decodeResult.remaining.text += "/" + data;
|
|
1820
|
+
}
|
|
1821
|
+
if (data.length > 1) {
|
|
1822
|
+
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
1823
|
+
}
|
|
1824
|
+
if (data.length > 2) {
|
|
1825
|
+
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
1826
|
+
}
|
|
1827
|
+
if (data.length > 3) {
|
|
1828
|
+
ResultFormatter.eta(decodeResult, data[3]);
|
|
1829
|
+
}
|
|
1830
|
+
if (data.length > 4) {
|
|
1831
|
+
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
1832
|
+
}
|
|
1833
|
+
if (data.length > 5) {
|
|
1834
|
+
allKnownFields = false;
|
|
1835
|
+
decodeResult.remaining.text += "," + data.slice(5).join(",");
|
|
1836
|
+
}
|
|
1837
|
+
return allKnownFields;
|
|
1838
|
+
}
|
|
1839
|
+
function processLR(decodeResult, data) {
|
|
1840
|
+
let allKnownFields = true;
|
|
1841
|
+
if (data.length === 19) {
|
|
1842
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1843
|
+
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
1844
|
+
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
1845
|
+
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
1846
|
+
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
1847
|
+
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
1848
|
+
allKnownFields = false;
|
|
1849
|
+
} else {
|
|
1850
|
+
allKnownFields = false;
|
|
1851
|
+
}
|
|
1852
|
+
return allKnownFields;
|
|
1853
|
+
}
|
|
1854
|
+
function parseMessageType(decodeResult, messageType) {
|
|
1855
|
+
let decoded = true;
|
|
1856
|
+
const parts = messageType.split("#");
|
|
1857
|
+
if (parts.length == 1) {
|
|
1858
|
+
if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
|
|
1859
|
+
decoded = processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
1860
|
+
}
|
|
1861
|
+
return decoded;
|
|
1862
|
+
} else if (parts.length == 2) {
|
|
1863
|
+
if (parts[0].length > 0) {
|
|
1864
|
+
decodeResult.remaining.text += parts[0].substring(0, 3);
|
|
1865
|
+
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
1866
|
+
decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
|
|
1867
|
+
}
|
|
1868
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
|
|
1869
|
+
decoded = processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
1870
|
+
}
|
|
1871
|
+
decodeResult.raw.message_type = messageType;
|
|
1872
|
+
return decoded;
|
|
1873
|
+
}
|
|
1874
|
+
decodeResult.remaining.text += messageType;
|
|
1875
|
+
return false;
|
|
1876
|
+
}
|
|
1877
|
+
function processDC(decodeResult, data) {
|
|
1878
|
+
decodeResult.raw.message_date = data[0];
|
|
1879
|
+
if (data.length === 1) {
|
|
1880
|
+
} else if (data.length === 2) {
|
|
1881
|
+
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
1882
|
+
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
1883
|
+
decodeResult.raw.message_timestamp = time;
|
|
1884
|
+
} else {
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1887
|
+
return true;
|
|
1888
|
+
}
|
|
1889
|
+
function processPS(decodeResult, data) {
|
|
1890
|
+
let allKnownFields = true;
|
|
1891
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1892
|
+
if (position) {
|
|
1893
|
+
decodeResult.raw.position = position;
|
|
1894
|
+
decodeResult.formatted.items.push({
|
|
1895
|
+
type: "aircraft_position",
|
|
1896
|
+
code: "POS",
|
|
1897
|
+
label: "Aircraft Position",
|
|
1898
|
+
value: CoordinateUtils.coordinateString(position)
|
|
1899
|
+
});
|
|
1900
|
+
} else {
|
|
1901
|
+
allKnownFields = false;
|
|
1902
|
+
}
|
|
1903
|
+
console.log("PS data.length: ", data.length);
|
|
1904
|
+
console.log("PS data: ", data);
|
|
1905
|
+
if (data.length === 9) {
|
|
1906
|
+
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
1907
|
+
ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
|
|
1908
|
+
ResultFormatter.temperature(decodeResult, data[6]);
|
|
1909
|
+
ResultFormatter.unknown(decodeResult, data[7]);
|
|
1910
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1911
|
+
}
|
|
1912
|
+
if (data.length === 14) {
|
|
1913
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
1914
|
+
processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
|
|
1915
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
1916
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
1917
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1918
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1919
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
1920
|
+
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
1921
|
+
}
|
|
1922
|
+
allKnownFields = false;
|
|
1923
|
+
return allKnownFields;
|
|
1924
|
+
}
|
|
1925
|
+
function processPosition2(decodeResult, data) {
|
|
1926
|
+
let allKnownFields = true;
|
|
1927
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1928
|
+
if (position) {
|
|
1929
|
+
decodeResult.raw.position = position;
|
|
1930
|
+
decodeResult.formatted.items.push({
|
|
1931
|
+
type: "aircraft_position",
|
|
1932
|
+
code: "POS",
|
|
1933
|
+
label: "Aircraft Position",
|
|
1934
|
+
value: CoordinateUtils.coordinateString(position)
|
|
1935
|
+
});
|
|
1936
|
+
} else {
|
|
1937
|
+
allKnownFields = false;
|
|
1938
|
+
}
|
|
1939
|
+
console.log("data.length: ", data.length);
|
|
1940
|
+
console.log("data: ", data);
|
|
1941
|
+
if (data.length >= 10) {
|
|
1942
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
1943
|
+
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
1944
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
1945
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
1946
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
1947
|
+
}
|
|
1948
|
+
if (data.length >= 14) {
|
|
1949
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
1950
|
+
ResultFormatter.unknown(decodeResult, data[11]);
|
|
1951
|
+
ResultFormatter.unknown(decodeResult, data[12]);
|
|
1952
|
+
ResultFormatter.unknown(decodeResult, data[13]);
|
|
1953
|
+
}
|
|
1954
|
+
allKnownFields = false;
|
|
1955
|
+
return allKnownFields;
|
|
1956
|
+
}
|
|
1957
|
+
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
1958
|
+
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
1959
|
+
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
1960
|
+
const timeFormat = date ? "epoch" : "tod";
|
|
1961
|
+
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
1962
|
+
lastWaypoint.time = lastTime;
|
|
1963
|
+
lastWaypoint.timeFormat = timeFormat;
|
|
1964
|
+
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
1965
|
+
nextWaypoint.time = nextTime;
|
|
1966
|
+
nextWaypoint.timeFormat = timeFormat;
|
|
1967
|
+
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
1968
|
+
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
1969
|
+
decodeResult.raw.route = { waypoints };
|
|
1970
|
+
decodeResult.formatted.items.push({
|
|
1971
|
+
type: "aircraft_route",
|
|
1972
|
+
code: "ROUTE",
|
|
1973
|
+
label: "Aircraft Route",
|
|
1974
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1507
1978
|
// lib/plugins/Label_H1_FPN.ts
|
|
1508
1979
|
var Label_H1_FPN = class extends DecoderPlugin {
|
|
1509
1980
|
name = "label-h1-fpn";
|
|
@@ -1518,15 +1989,73 @@ var Label_H1_FPN = class extends DecoderPlugin {
|
|
|
1518
1989
|
decodeResult.decoder.name = this.name;
|
|
1519
1990
|
decodeResult.formatted.description = "Flight Plan";
|
|
1520
1991
|
decodeResult.message = message;
|
|
1992
|
+
decodeResult.remaining.text = "";
|
|
1521
1993
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
1522
|
-
const
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1994
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
1995
|
+
decodeResult.decoded = true;
|
|
1996
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
1997
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
1998
|
+
if (options?.debug) {
|
|
1999
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2000
|
+
}
|
|
2001
|
+
decodeResult.remaining.text = message.text;
|
|
2002
|
+
decodeResult.decoded = false;
|
|
2003
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2004
|
+
}
|
|
2005
|
+
return decodeResult;
|
|
2006
|
+
}
|
|
2007
|
+
};
|
|
2008
|
+
|
|
2009
|
+
// lib/plugins/Label_H1_FTX.ts
|
|
2010
|
+
var Label_H1_FTX = class extends DecoderPlugin {
|
|
2011
|
+
name = "label-h1-ftx";
|
|
2012
|
+
qualifiers() {
|
|
2013
|
+
return {
|
|
2014
|
+
labels: ["H1"],
|
|
2015
|
+
preambles: ["FTX", "- #MDFTX"]
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
decode(message, options = {}) {
|
|
2019
|
+
let decodeResult = this.defaultResult();
|
|
2020
|
+
decodeResult.decoder.name = this.name;
|
|
2021
|
+
decodeResult.formatted.description = "Free Text";
|
|
2022
|
+
decodeResult.message = message;
|
|
2023
|
+
decodeResult.remaining.text = "";
|
|
2024
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2025
|
+
decodeResult.decoded = true;
|
|
2026
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2027
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2028
|
+
if (options?.debug) {
|
|
2029
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2030
|
+
}
|
|
2031
|
+
decodeResult.remaining.text = message.text;
|
|
2032
|
+
decodeResult.decoded = false;
|
|
2033
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2034
|
+
}
|
|
2035
|
+
return decodeResult;
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
|
|
2039
|
+
// lib/plugins/Label_H1_INI.ts
|
|
2040
|
+
var Label_H1_INI = class extends DecoderPlugin {
|
|
2041
|
+
// eslint-disable-line camelcase
|
|
2042
|
+
name = "label-h1-ini";
|
|
2043
|
+
qualifiers() {
|
|
2044
|
+
return {
|
|
2045
|
+
labels: ["H1"],
|
|
2046
|
+
preambles: ["INI", "- #MDINI"]
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
decode(message, options = {}) {
|
|
2050
|
+
const decodeResult = this.defaultResult();
|
|
2051
|
+
decodeResult.decoder.name = this.name;
|
|
2052
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2053
|
+
decodeResult.message = message;
|
|
2054
|
+
decodeResult.remaining.text = "";
|
|
2055
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2056
|
+
decodeResult.decoded = true;
|
|
2057
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2058
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
1530
2059
|
if (options?.debug) {
|
|
1531
2060
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1532
2061
|
}
|
|
@@ -1537,15 +2066,6 @@ var Label_H1_FPN = class extends DecoderPlugin {
|
|
|
1537
2066
|
return decodeResult;
|
|
1538
2067
|
}
|
|
1539
2068
|
};
|
|
1540
|
-
function addChecksum(decodeResult, value) {
|
|
1541
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1542
|
-
decodeResult.formatted.items.push({
|
|
1543
|
-
type: "message_checksum",
|
|
1544
|
-
code: "CHECKSUM",
|
|
1545
|
-
label: "Message Checksum",
|
|
1546
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
2069
|
|
|
1550
2070
|
// lib/plugins/Label_H1_OHMA.ts
|
|
1551
2071
|
import * as zlib from "minizlib";
|
|
@@ -1571,13 +2091,18 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
1571
2091
|
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
1572
2092
|
const result = decompress.read();
|
|
1573
2093
|
const jsonText = result.toString();
|
|
1574
|
-
const json = JSON.parse(jsonText);
|
|
1575
2094
|
let formattedMsg;
|
|
1576
|
-
|
|
1577
|
-
|
|
2095
|
+
let jsonMessage;
|
|
2096
|
+
try {
|
|
2097
|
+
jsonMessage = JSON.parse(jsonText).message;
|
|
2098
|
+
} catch {
|
|
2099
|
+
jsonMessage = jsonText;
|
|
2100
|
+
}
|
|
2101
|
+
try {
|
|
2102
|
+
const ohmaMsg = JSON.parse(jsonMessage);
|
|
1578
2103
|
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
1579
|
-
}
|
|
1580
|
-
formattedMsg =
|
|
2104
|
+
} catch {
|
|
2105
|
+
formattedMsg = jsonMessage;
|
|
1581
2106
|
}
|
|
1582
2107
|
decodeResult.decoded = true;
|
|
1583
2108
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1616,225 +2141,20 @@ var Label_H1_POS = class extends DecoderPlugin {
|
|
|
1616
2141
|
decodeResult.formatted.description = "Position Report";
|
|
1617
2142
|
decodeResult.message = message;
|
|
1618
2143
|
decodeResult.remaining.text = "";
|
|
1619
|
-
const
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
if (decoded) {
|
|
1625
|
-
processChecksum(decodeResult, checksum);
|
|
1626
|
-
decodeResult.decoded = true;
|
|
1627
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
1628
|
-
} else if (decodeResult.remaining.text.length > 0) {
|
|
1629
|
-
processChecksum(decodeResult, checksum);
|
|
1630
|
-
decodeResult.decoded = true;
|
|
1631
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1632
|
-
} else {
|
|
1633
|
-
decodeResult.decoded = false;
|
|
1634
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1635
|
-
}
|
|
1636
|
-
} else if (parts.length === 10) {
|
|
1637
|
-
processAlt(decodeResult, parts[3]);
|
|
1638
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
|
|
1639
|
-
processTemp(decodeResult, parts[7]);
|
|
1640
|
-
processUnknown(decodeResult, parts[8]);
|
|
1641
|
-
processUnknown(decodeResult, parts[9]);
|
|
1642
|
-
processChecksum(decodeResult, checksum);
|
|
1643
|
-
decodeResult.decoded = true;
|
|
1644
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1645
|
-
} else if (parts.length === 11) {
|
|
1646
|
-
processAlt(decodeResult, parts[3]);
|
|
1647
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
|
|
1648
|
-
processTemp(decodeResult, parts[7]);
|
|
1649
|
-
processUnknown(decodeResult, parts[8]);
|
|
1650
|
-
processUnknown(decodeResult, parts[9]);
|
|
1651
|
-
processChecksum(decodeResult, checksum);
|
|
1652
|
-
decodeResult.decoded = true;
|
|
1653
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1654
|
-
} else if (parts.length === 12) {
|
|
1655
|
-
const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
|
|
1656
|
-
processUnknown(decodeResult, parts[3]);
|
|
1657
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
|
|
1658
|
-
processTemp(decodeResult, parts[7]);
|
|
1659
|
-
processUnknown(decodeResult, parts[8]);
|
|
1660
|
-
processUnknown(decodeResult, parts[9]);
|
|
1661
|
-
processUnknown(decodeResult, parts[10]);
|
|
1662
|
-
processChecksum(decodeResult, checksum);
|
|
1663
|
-
decodeResult.decoded = true;
|
|
1664
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1665
|
-
} else if (parts.length === 14) {
|
|
1666
|
-
processAlt(decodeResult, parts[3]);
|
|
1667
|
-
processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
|
|
1668
|
-
processTemp(decodeResult, parts[7]);
|
|
1669
|
-
processUnknown(decodeResult, parts[8]);
|
|
1670
|
-
processUnknown(decodeResult, parts[9]);
|
|
1671
|
-
processGndspd(decodeResult, parts[10]);
|
|
1672
|
-
processUnknown(decodeResult, parts[11]);
|
|
1673
|
-
processUnknown(decodeResult, parts[12]);
|
|
1674
|
-
processUnknown(decodeResult, parts[13]);
|
|
1675
|
-
processChecksum(decodeResult, checksum);
|
|
1676
|
-
decodeResult.decoded = true;
|
|
1677
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1678
|
-
} else if (parts.length === 15) {
|
|
1679
|
-
decodeResult.raw.flight_number = parts[1];
|
|
1680
|
-
let date = void 0;
|
|
1681
|
-
if (parts[2].startsWith("/DC")) {
|
|
1682
|
-
date = parts[2].substring(3);
|
|
1683
|
-
} else {
|
|
1684
|
-
processUnknown(decodeResult, parts[2]);
|
|
1685
|
-
}
|
|
1686
|
-
processUnknown(decodeResult, parts[3]);
|
|
1687
|
-
const fields = parts[4].split("/");
|
|
1688
|
-
for (let i = 0; i < fields.length; ++i) {
|
|
1689
|
-
const field = fields[i];
|
|
1690
|
-
if (field.startsWith("PS")) {
|
|
1691
|
-
processPosition2(decodeResult, field.substring(2));
|
|
1692
|
-
} else {
|
|
1693
|
-
if (i === 0) {
|
|
1694
|
-
processUnknown(decodeResult, field);
|
|
1695
|
-
} else {
|
|
1696
|
-
processUnknown(decodeResult, "/" + field);
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
|
|
1701
|
-
processAlt(decodeResult, parts[6]);
|
|
1702
|
-
processTemp(decodeResult, parts[10]);
|
|
1703
|
-
processUnknown(decodeResult, parts[11]);
|
|
1704
|
-
processUnknown(decodeResult, parts[12]);
|
|
1705
|
-
processUnknown(decodeResult, parts[13]);
|
|
1706
|
-
processUnknown(decodeResult, parts[14]);
|
|
1707
|
-
processChecksum(decodeResult, checksum);
|
|
1708
|
-
decodeResult.decoded = true;
|
|
1709
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1710
|
-
} else if (parts.length === 21) {
|
|
1711
|
-
processRunway(decodeResult, parts[1]);
|
|
1712
|
-
processUnknown(decodeResult, parts.slice(2, 11).join(","));
|
|
1713
|
-
processTemp(decodeResult, parts[11]);
|
|
1714
|
-
processUnknown(decodeResult, parts.slice(12, 20).join(","));
|
|
1715
|
-
FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
|
|
1716
|
-
processChecksum(decodeResult, checksum);
|
|
1717
|
-
decodeResult.decoded = true;
|
|
1718
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1719
|
-
} else if (parts.length === 32) {
|
|
1720
|
-
processRunway(decodeResult, parts[1]);
|
|
1721
|
-
const time = parts[2];
|
|
1722
|
-
processUnknown(decodeResult, parts[3]);
|
|
1723
|
-
const past = parts[4];
|
|
1724
|
-
processUnknown(decodeResult, parts[5]);
|
|
1725
|
-
const eta = parts[6];
|
|
1726
|
-
const next = parts[7];
|
|
1727
|
-
processUnknown(decodeResult, parts.slice(8, 14).join(","));
|
|
1728
|
-
processUnknown(decodeResult, parts[16]);
|
|
1729
|
-
processUnknown(decodeResult, parts[17]);
|
|
1730
|
-
processUnknown(decodeResult, parts[18]);
|
|
1731
|
-
processGndspd(decodeResult, parts[19]);
|
|
1732
|
-
processUnknown(decodeResult, parts[20]);
|
|
1733
|
-
processUnknown(decodeResult, parts[21]);
|
|
1734
|
-
processAlt(decodeResult, parts[22]);
|
|
1735
|
-
processUnknown(decodeResult, parts.slice(23, 31).join(","));
|
|
1736
|
-
const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
|
|
1737
|
-
processRoute(decodeResult, past, time, next, eta);
|
|
1738
|
-
decodeResult.decoded = true;
|
|
1739
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1740
|
-
} else {
|
|
1741
|
-
if (options.debug) {
|
|
2144
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2145
|
+
decodeResult.decoded = true;
|
|
2146
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2147
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2148
|
+
if (options?.debug) {
|
|
1742
2149
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1743
2150
|
}
|
|
1744
|
-
decodeResult.remaining.text
|
|
2151
|
+
decodeResult.remaining.text = message.text;
|
|
1745
2152
|
decodeResult.decoded = false;
|
|
1746
2153
|
decodeResult.decoder.decodeLevel = "none";
|
|
1747
2154
|
}
|
|
1748
2155
|
return decodeResult;
|
|
1749
2156
|
}
|
|
1750
2157
|
};
|
|
1751
|
-
function processUnknown(decodeResult, value) {
|
|
1752
|
-
decodeResult.remaining.text += "," + value;
|
|
1753
|
-
}
|
|
1754
|
-
function processPosition2(decodeResult, value) {
|
|
1755
|
-
const position = CoordinateUtils.decodeStringCoordinates(value);
|
|
1756
|
-
if (position) {
|
|
1757
|
-
decodeResult.raw.position = position;
|
|
1758
|
-
decodeResult.formatted.items.push({
|
|
1759
|
-
type: "aircraft_position",
|
|
1760
|
-
code: "POS",
|
|
1761
|
-
label: "Aircraft Position",
|
|
1762
|
-
value: CoordinateUtils.coordinateString(position)
|
|
1763
|
-
});
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
function processAlt(decodeResult, value) {
|
|
1767
|
-
decodeResult.raw.altitude = Number(value) * 100;
|
|
1768
|
-
decodeResult.formatted.items.push({
|
|
1769
|
-
type: "altitude",
|
|
1770
|
-
code: "ALT",
|
|
1771
|
-
label: "Altitude",
|
|
1772
|
-
value: `${decodeResult.raw.altitude} feet`
|
|
1773
|
-
});
|
|
1774
|
-
}
|
|
1775
|
-
function processTemp(decodeResult, value) {
|
|
1776
|
-
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1777
|
-
decodeResult.formatted.items.push({
|
|
1778
|
-
type: "outside_air_temperature",
|
|
1779
|
-
code: "OATEMP",
|
|
1780
|
-
label: "Outside Air Temperature (C)",
|
|
1781
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
function processRunway(decodeResult, value) {
|
|
1785
|
-
decodeResult.raw.arrival_runway = value.replace("RW", "");
|
|
1786
|
-
decodeResult.formatted.items.push({
|
|
1787
|
-
type: "runway",
|
|
1788
|
-
label: "Arrival Runway",
|
|
1789
|
-
value: decodeResult.raw.arrival_runway
|
|
1790
|
-
});
|
|
1791
|
-
}
|
|
1792
|
-
function processGndspd(decodeResult, value) {
|
|
1793
|
-
decodeResult.raw.groundspeed = Number(value);
|
|
1794
|
-
decodeResult.formatted.items.push({
|
|
1795
|
-
type: "aircraft_groundspeed",
|
|
1796
|
-
code: "GSPD",
|
|
1797
|
-
label: "Aircraft Groundspeed",
|
|
1798
|
-
value: `${decodeResult.raw.groundspeed}`
|
|
1799
|
-
});
|
|
1800
|
-
}
|
|
1801
|
-
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
1802
|
-
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
1803
|
-
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
1804
|
-
const timeFormat = date ? "epoch" : "tod";
|
|
1805
|
-
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
1806
|
-
lastWaypoint.time = lastTime;
|
|
1807
|
-
lastWaypoint.timeFormat = timeFormat;
|
|
1808
|
-
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
1809
|
-
nextWaypoint.time = nextTime;
|
|
1810
|
-
nextWaypoint.timeFormat = timeFormat;
|
|
1811
|
-
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
1812
|
-
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
1813
|
-
decodeResult.raw.route = { waypoints };
|
|
1814
|
-
decodeResult.formatted.items.push({
|
|
1815
|
-
type: "aircraft_route",
|
|
1816
|
-
code: "ROUTE",
|
|
1817
|
-
label: "Aircraft Route",
|
|
1818
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1819
|
-
});
|
|
1820
|
-
}
|
|
1821
|
-
function processChecksum(decodeResult, value) {
|
|
1822
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1823
|
-
decodeResult.formatted.items.push({
|
|
1824
|
-
type: "message_checksum",
|
|
1825
|
-
code: "CHECKSUM",
|
|
1826
|
-
label: "Message Checksum",
|
|
1827
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1828
|
-
});
|
|
1829
|
-
}
|
|
1830
|
-
function findHeader(text) {
|
|
1831
|
-
const parts = text.split(",");
|
|
1832
|
-
const header = parts[0];
|
|
1833
|
-
if (header.indexOf("/TS") === -1) {
|
|
1834
|
-
return header;
|
|
1835
|
-
}
|
|
1836
|
-
return parts[0] + "," + parts[1];
|
|
1837
|
-
}
|
|
1838
2158
|
|
|
1839
2159
|
// lib/plugins/Label_H1_WRN.ts
|
|
1840
2160
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
@@ -2989,6 +3309,7 @@ var MessageDecoder = class {
|
|
|
2989
3309
|
this.registerPlugin(new Label_15_FST(this));
|
|
2990
3310
|
this.registerPlugin(new Label_16_N_Space(this));
|
|
2991
3311
|
this.registerPlugin(new Label_20_POS(this));
|
|
3312
|
+
this.registerPlugin(new Label_21_POS(this));
|
|
2992
3313
|
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
2993
3314
|
this.registerPlugin(new Label_44_ETA(this));
|
|
2994
3315
|
this.registerPlugin(new Label_44_IN(this));
|
|
@@ -2997,6 +3318,9 @@ var MessageDecoder = class {
|
|
|
2997
3318
|
this.registerPlugin(new Label_44_POS(this));
|
|
2998
3319
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
2999
3320
|
this.registerPlugin(new Label_H1_FPN(this));
|
|
3321
|
+
this.registerPlugin(new Label_H1_FLR(this));
|
|
3322
|
+
this.registerPlugin(new Label_H1_FTX(this));
|
|
3323
|
+
this.registerPlugin(new Label_H1_INI(this));
|
|
3000
3324
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
3001
3325
|
this.registerPlugin(new Label_H1_POS(this));
|
|
3002
3326
|
this.registerPlugin(new Label_H1_WRN(this));
|