@airframes/acars-decoder 1.6.11 → 1.6.12
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 +860 -627
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +860 -627
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49,6 +49,74 @@ var IcaoDecoder = class {
|
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
+
// lib/DateTimeUtils.ts
|
|
53
|
+
var DateTimeUtils = class {
|
|
54
|
+
// Expects a four digit UTC time string (HHMM)
|
|
55
|
+
static UTCToString(UTCString) {
|
|
56
|
+
let utcDate = /* @__PURE__ */ new Date();
|
|
57
|
+
utcDate.setUTCHours(+UTCString.substr(0, 2), +UTCString.substr(2, 2), 0);
|
|
58
|
+
return utcDate.toTimeString();
|
|
59
|
+
}
|
|
60
|
+
// Expects a six digit date string and a four digit UTC time string
|
|
61
|
+
// (DDMMYY) (HHMM)
|
|
62
|
+
static UTCDateTimeToString(dateString, timeString) {
|
|
63
|
+
let utcDate = /* @__PURE__ */ new Date();
|
|
64
|
+
utcDate.setUTCDate(+dateString.substr(0, 2));
|
|
65
|
+
utcDate.setUTCMonth(+dateString.substr(2, 2));
|
|
66
|
+
if (dateString.length === 6) {
|
|
67
|
+
utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
|
|
68
|
+
}
|
|
69
|
+
if (timeString.length === 6) {
|
|
70
|
+
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), +timeString.substr(4, 2));
|
|
71
|
+
} else {
|
|
72
|
+
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), 0);
|
|
73
|
+
}
|
|
74
|
+
return utcDate.toUTCString();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param time HHMMSS
|
|
79
|
+
* @returns seconds since midnight
|
|
80
|
+
*/
|
|
81
|
+
static convertHHMMSSToTod(time) {
|
|
82
|
+
const h = Number(time.substring(0, 2));
|
|
83
|
+
const m = Number(time.substring(2, 4));
|
|
84
|
+
const s = Number(time.substring(4, 6));
|
|
85
|
+
const tod = h * 3600 + m * 60 + s;
|
|
86
|
+
return tod;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @param time HHMMSS
|
|
91
|
+
* @param date MMDDYY or MMDDYYYY
|
|
92
|
+
* @returns seconds since epoch
|
|
93
|
+
*/
|
|
94
|
+
static convertDateTimeToEpoch(time, date) {
|
|
95
|
+
if (date.length === 6) {
|
|
96
|
+
date = date.substring(0, 4) + `20${date.substring(4, 6)}`;
|
|
97
|
+
}
|
|
98
|
+
const timestamp = `${date.substring(4, 8)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
|
|
99
|
+
const millis = Date.parse(timestamp);
|
|
100
|
+
return millis / 1e3;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Converts a timestamp to a string
|
|
104
|
+
*
|
|
105
|
+
* ISO-8601 format for 'epoch'
|
|
106
|
+
* HH:MM:SS for 'tod'
|
|
107
|
+
* @param time
|
|
108
|
+
* @param format
|
|
109
|
+
* @returns
|
|
110
|
+
*/
|
|
111
|
+
static timestampToString(time, format) {
|
|
112
|
+
const date = new Date(time * 1e3);
|
|
113
|
+
if (format == "tod") {
|
|
114
|
+
return date.toISOString().slice(11, 19);
|
|
115
|
+
}
|
|
116
|
+
return date.toISOString().slice(0, -5) + "Z";
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
52
120
|
// lib/DecoderPlugin.ts
|
|
53
121
|
var DecoderPlugin = class {
|
|
54
122
|
decoder;
|
|
@@ -167,8 +235,124 @@ var CoordinateUtils = class {
|
|
|
167
235
|
}
|
|
168
236
|
};
|
|
169
237
|
|
|
238
|
+
// lib/utils/route_utils.ts
|
|
239
|
+
var RouteUtils = class _RouteUtils {
|
|
240
|
+
static formatFlightState(state) {
|
|
241
|
+
switch (state) {
|
|
242
|
+
case "TO":
|
|
243
|
+
return "Takeoff";
|
|
244
|
+
case "IC":
|
|
245
|
+
return "Initial Climb";
|
|
246
|
+
case "CL":
|
|
247
|
+
return "Climb";
|
|
248
|
+
case "ER":
|
|
249
|
+
return "En Route";
|
|
250
|
+
case "DC":
|
|
251
|
+
return "Descent";
|
|
252
|
+
case "AP":
|
|
253
|
+
return "Approach";
|
|
254
|
+
default:
|
|
255
|
+
return `Unknown ${state}`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
static routeToString(route) {
|
|
259
|
+
let str = "";
|
|
260
|
+
if (route.name) {
|
|
261
|
+
str += route.name;
|
|
262
|
+
}
|
|
263
|
+
if (route.runway) {
|
|
264
|
+
str += `(${route.runway})`;
|
|
265
|
+
}
|
|
266
|
+
if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
|
|
267
|
+
str += " starting at ";
|
|
268
|
+
} else if (str.length !== 0 && route.waypoints) {
|
|
269
|
+
str += ": ";
|
|
270
|
+
}
|
|
271
|
+
if (route.waypoints) {
|
|
272
|
+
str += _RouteUtils.waypointsToString(route.waypoints);
|
|
273
|
+
}
|
|
274
|
+
return str;
|
|
275
|
+
}
|
|
276
|
+
static waypointToString(waypoint) {
|
|
277
|
+
let s = waypoint.name;
|
|
278
|
+
if (waypoint.latitude && waypoint.longitude) {
|
|
279
|
+
s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
|
|
280
|
+
}
|
|
281
|
+
if (waypoint.offset) {
|
|
282
|
+
s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
|
|
283
|
+
}
|
|
284
|
+
if (waypoint.time && waypoint.timeFormat) {
|
|
285
|
+
s += `@${DateTimeUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
|
|
286
|
+
}
|
|
287
|
+
return s;
|
|
288
|
+
}
|
|
289
|
+
static getWaypoint(leg) {
|
|
290
|
+
const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
|
|
291
|
+
if (regex?.length == 4) {
|
|
292
|
+
return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
|
|
293
|
+
}
|
|
294
|
+
const waypoint = leg.split(",");
|
|
295
|
+
if (waypoint.length == 2) {
|
|
296
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
297
|
+
if (position) {
|
|
298
|
+
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (leg.length == 13 || leg.length == 14) {
|
|
302
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
303
|
+
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
304
|
+
if (position) {
|
|
305
|
+
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return { name: leg };
|
|
309
|
+
}
|
|
310
|
+
static waypointsToString(waypoints) {
|
|
311
|
+
let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
|
|
312
|
+
if (str.startsWith(" > ")) {
|
|
313
|
+
str = ">>" + str.slice(2);
|
|
314
|
+
}
|
|
315
|
+
return str;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
170
319
|
// lib/utils/result_formatter.ts
|
|
171
320
|
var ResultFormatter = class {
|
|
321
|
+
static state_change(decodeResult, from, to) {
|
|
322
|
+
decodeResult.raw.state_change = {
|
|
323
|
+
from,
|
|
324
|
+
to
|
|
325
|
+
};
|
|
326
|
+
from = RouteUtils.formatFlightState(from);
|
|
327
|
+
to = RouteUtils.formatFlightState(to);
|
|
328
|
+
decodeResult.formatted.items.push({
|
|
329
|
+
type: "state_change",
|
|
330
|
+
code: "STATE_CHANGE",
|
|
331
|
+
label: "State Change",
|
|
332
|
+
value: `${from} -> ${to}`
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
static freetext(decodeResult, value) {
|
|
336
|
+
decodeResult.raw.freetext = value;
|
|
337
|
+
decodeResult.formatted.items.push({
|
|
338
|
+
type: "freetext",
|
|
339
|
+
code: "FREE_TEXT",
|
|
340
|
+
label: "Free Text",
|
|
341
|
+
value
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
static door_event(decodeResult, name, state) {
|
|
345
|
+
decodeResult.raw.door_event = {
|
|
346
|
+
door: name,
|
|
347
|
+
state
|
|
348
|
+
};
|
|
349
|
+
decodeResult.formatted.items.push({
|
|
350
|
+
type: "door_event",
|
|
351
|
+
code: "DOOR",
|
|
352
|
+
label: "Door Event",
|
|
353
|
+
value: `${name} ${state}`
|
|
354
|
+
});
|
|
355
|
+
}
|
|
172
356
|
static position(decodeResult, value) {
|
|
173
357
|
decodeResult.raw.position = value;
|
|
174
358
|
decodeResult.formatted.items.push({
|
|
@@ -189,16 +373,41 @@ var ResultFormatter = class {
|
|
|
189
373
|
}
|
|
190
374
|
static flightNumber(decodeResult, value) {
|
|
191
375
|
decodeResult.raw.flight_number = value;
|
|
376
|
+
decodeResult.formatted.items.push({
|
|
377
|
+
type: "flight_number",
|
|
378
|
+
code: "FLIGHT",
|
|
379
|
+
label: "Flight Number",
|
|
380
|
+
value: decodeResult.raw.flight_number
|
|
381
|
+
});
|
|
192
382
|
}
|
|
193
|
-
static
|
|
194
|
-
decodeResult.raw.
|
|
383
|
+
static callsign(decodeResult, value) {
|
|
384
|
+
decodeResult.raw.callsign = value;
|
|
195
385
|
decodeResult.formatted.items.push({
|
|
196
|
-
type: "
|
|
197
|
-
code: "
|
|
198
|
-
label: "
|
|
199
|
-
value: decodeResult.raw.
|
|
386
|
+
type: "callsign",
|
|
387
|
+
code: "CALLSIGN",
|
|
388
|
+
label: "Callsign",
|
|
389
|
+
value: decodeResult.raw.callsign
|
|
200
390
|
});
|
|
201
391
|
}
|
|
392
|
+
static departureAirport(decodeResult, value, type = "ICAO") {
|
|
393
|
+
if (type === "ICAO") {
|
|
394
|
+
decodeResult.raw.departure_icao = value;
|
|
395
|
+
decodeResult.formatted.items.push({
|
|
396
|
+
type: "icao",
|
|
397
|
+
code: "ORG",
|
|
398
|
+
label: "Origin",
|
|
399
|
+
value
|
|
400
|
+
});
|
|
401
|
+
} else {
|
|
402
|
+
decodeResult.raw.departure_iata = value;
|
|
403
|
+
decodeResult.formatted.items.push({
|
|
404
|
+
type: "iata",
|
|
405
|
+
code: "ORG",
|
|
406
|
+
label: "Origin",
|
|
407
|
+
value
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
202
411
|
static departureRunway(decodeResult, value) {
|
|
203
412
|
decodeResult.raw.departure_runway = value;
|
|
204
413
|
decodeResult.formatted.items.push({
|
|
@@ -208,33 +417,52 @@ var ResultFormatter = class {
|
|
|
208
417
|
value: decodeResult.raw.departure_runway
|
|
209
418
|
});
|
|
210
419
|
}
|
|
211
|
-
static arrivalAirport(decodeResult, value) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
420
|
+
static arrivalAirport(decodeResult, value, type = "ICAO") {
|
|
421
|
+
if (type === "ICAO") {
|
|
422
|
+
decodeResult.raw.arrival_icao = value;
|
|
423
|
+
decodeResult.formatted.items.push({
|
|
424
|
+
type: "icao",
|
|
425
|
+
code: "DST",
|
|
426
|
+
label: "Destination",
|
|
427
|
+
value
|
|
428
|
+
});
|
|
429
|
+
} else {
|
|
430
|
+
decodeResult.raw.arrival_iata = value;
|
|
431
|
+
decodeResult.formatted.items.push({
|
|
432
|
+
type: "iata",
|
|
433
|
+
code: "DST",
|
|
434
|
+
label: "Destination",
|
|
435
|
+
value
|
|
436
|
+
});
|
|
437
|
+
}
|
|
219
438
|
}
|
|
220
439
|
static alternateAirport(decodeResult, value) {
|
|
221
440
|
decodeResult.raw.alternate_icao = value;
|
|
222
441
|
decodeResult.formatted.items.push({
|
|
223
|
-
type: "
|
|
442
|
+
type: "icao",
|
|
224
443
|
code: "ALT_DST",
|
|
225
444
|
label: "Alternate Destination",
|
|
226
445
|
value: decodeResult.raw.alternate_icao
|
|
227
446
|
});
|
|
228
447
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
448
|
+
static eta(decodeResult, time, type = "tod") {
|
|
449
|
+
if (type === "tod") {
|
|
450
|
+
decodeResult.raw.eta_time = time;
|
|
451
|
+
decodeResult.formatted.items.push({
|
|
452
|
+
type: "time_of_day",
|
|
453
|
+
code: "ETA",
|
|
454
|
+
label: "Estimated Time of Arrival",
|
|
455
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
456
|
+
});
|
|
457
|
+
} else {
|
|
458
|
+
decodeResult.raw.eta_date = time;
|
|
459
|
+
decodeResult.formatted.items.push({
|
|
460
|
+
type: "epoch",
|
|
461
|
+
code: "ETA",
|
|
462
|
+
label: "Estimated Time of Arrival",
|
|
463
|
+
value: DateTimeUtils.timestampToString(time, "epoch")
|
|
464
|
+
});
|
|
465
|
+
}
|
|
238
466
|
}
|
|
239
467
|
static arrivalRunway(decodeResult, value) {
|
|
240
468
|
decodeResult.raw.arrival_runway = value;
|
|
@@ -291,12 +519,12 @@ var ResultFormatter = class {
|
|
|
291
519
|
});
|
|
292
520
|
}
|
|
293
521
|
static temperature(decodeResult, value) {
|
|
294
|
-
decodeResult.raw.outside_air_temperature = Number(value.
|
|
522
|
+
decodeResult.raw.outside_air_temperature = Number(value.replace("M", "-").replace("P", "+"));
|
|
295
523
|
decodeResult.formatted.items.push({
|
|
296
524
|
type: "outside_air_temperature",
|
|
297
525
|
code: "OATEMP",
|
|
298
526
|
label: "Outside Air Temperature (C)",
|
|
299
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
527
|
+
value: `${decodeResult.raw.outside_air_temperature} degrees`
|
|
300
528
|
});
|
|
301
529
|
}
|
|
302
530
|
static heading(decodeResult, value) {
|
|
@@ -319,42 +547,56 @@ var ResultFormatter = class {
|
|
|
319
547
|
}
|
|
320
548
|
static out(decodeResult, time) {
|
|
321
549
|
decodeResult.raw.out_time = time;
|
|
322
|
-
const date = new Date(time * 1e3);
|
|
323
550
|
decodeResult.formatted.items.push({
|
|
324
551
|
type: "time_of_day",
|
|
325
552
|
code: "OUT",
|
|
326
553
|
label: "Out of Gate Time",
|
|
327
|
-
value:
|
|
554
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
328
555
|
});
|
|
329
556
|
}
|
|
330
557
|
static off(decodeResult, time) {
|
|
331
558
|
decodeResult.raw.off_time = time;
|
|
332
|
-
const date = new Date(time * 1e3);
|
|
333
559
|
decodeResult.formatted.items.push({
|
|
334
560
|
type: "time_of_day",
|
|
335
561
|
code: "OFF",
|
|
336
562
|
label: "Takeoff Time",
|
|
337
|
-
value:
|
|
563
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
338
564
|
});
|
|
339
565
|
}
|
|
340
566
|
static on(decodeResult, time) {
|
|
341
567
|
decodeResult.raw.on_time = time;
|
|
342
|
-
const date = new Date(time * 1e3);
|
|
343
568
|
decodeResult.formatted.items.push({
|
|
344
569
|
type: "time_of_day",
|
|
345
570
|
code: "ON",
|
|
346
571
|
label: "Landing Time",
|
|
347
|
-
value:
|
|
572
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
348
573
|
});
|
|
349
574
|
}
|
|
350
575
|
static in(decodeResult, time) {
|
|
351
576
|
decodeResult.raw.in_time = time;
|
|
352
|
-
const date = new Date(time * 1e3);
|
|
353
577
|
decodeResult.formatted.items.push({
|
|
354
578
|
type: "time_of_day",
|
|
355
579
|
code: "IN",
|
|
356
580
|
label: "In Gate Time",
|
|
357
|
-
value:
|
|
581
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
static time_of_day(decodeResult, time) {
|
|
585
|
+
decodeResult.raw.time_of_day = time;
|
|
586
|
+
decodeResult.formatted.items.push({
|
|
587
|
+
type: "time_of_day",
|
|
588
|
+
code: "MSG_TOD",
|
|
589
|
+
label: "Message Timestamp",
|
|
590
|
+
value: DateTimeUtils.timestampToString(time, "tod")
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
static text(decodeResult, text2) {
|
|
594
|
+
decodeResult.raw.text = text2;
|
|
595
|
+
decodeResult.formatted.items.push({
|
|
596
|
+
type: "text",
|
|
597
|
+
code: "TEXT",
|
|
598
|
+
label: "Text Message",
|
|
599
|
+
value: text2
|
|
358
600
|
});
|
|
359
601
|
}
|
|
360
602
|
static unknown(decodeResult, value) {
|
|
@@ -362,9 +604,9 @@ var ResultFormatter = class {
|
|
|
362
604
|
}
|
|
363
605
|
};
|
|
364
606
|
|
|
365
|
-
// lib/plugins/
|
|
366
|
-
var
|
|
367
|
-
name = "label-5z";
|
|
607
|
+
// lib/plugins/Label_5Z_Slash.ts
|
|
608
|
+
var Label_5Z_Slash = class extends DecoderPlugin {
|
|
609
|
+
name = "label-5z-slash";
|
|
368
610
|
descriptions = {
|
|
369
611
|
B1: "Request Weight and Balance",
|
|
370
612
|
B3: "Request Departure Clearance",
|
|
@@ -382,6 +624,7 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
382
624
|
D6: "From-To + Date",
|
|
383
625
|
D7: "From-To + Alternate + Time",
|
|
384
626
|
EO: "In Range",
|
|
627
|
+
ET: "Expected Time",
|
|
385
628
|
PW: "Position Weather",
|
|
386
629
|
RL: "Request Release",
|
|
387
630
|
R3: "Request HOWGOZIT Message",
|
|
@@ -392,48 +635,82 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
392
635
|
};
|
|
393
636
|
qualifiers() {
|
|
394
637
|
return {
|
|
395
|
-
labels: ["5Z"]
|
|
638
|
+
labels: ["5Z"],
|
|
639
|
+
preambles: ["/"]
|
|
396
640
|
};
|
|
397
641
|
}
|
|
398
642
|
decode(message, options = {}) {
|
|
399
643
|
const decodeResult = this.defaultResult();
|
|
400
644
|
decodeResult.decoder.name = this.name;
|
|
401
645
|
decodeResult.formatted.description = "Airline Designated Downlink";
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
646
|
+
const lines = message.text.split("\r\n");
|
|
647
|
+
if (lines[0] === "/TXT") {
|
|
648
|
+
ResultFormatter.text(decodeResult, lines.slice(1).join("\r\n"));
|
|
649
|
+
decodeResult.decoded = true;
|
|
650
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
651
|
+
return decodeResult;
|
|
652
|
+
}
|
|
653
|
+
const data = lines[0].split("/");
|
|
654
|
+
const header = data[1].split(" ");
|
|
655
|
+
const type = header[0];
|
|
656
|
+
const typeDescription = this.descriptions[type];
|
|
657
|
+
if (typeDescription) {
|
|
408
658
|
decodeResult.raw.airline = "United Airlines";
|
|
409
659
|
decodeResult.formatted.items.push({
|
|
410
660
|
type: "airline",
|
|
661
|
+
code: "AIRLINE",
|
|
411
662
|
label: "Airline",
|
|
412
663
|
value: "United Airlines"
|
|
413
664
|
});
|
|
414
665
|
decodeResult.raw.message_type = type;
|
|
415
666
|
decodeResult.formatted.items.push({
|
|
416
667
|
type: "message_type",
|
|
668
|
+
code: "MSG_TYPE",
|
|
417
669
|
label: "Message Type",
|
|
418
670
|
value: `${typeDescription} (${type})`
|
|
419
671
|
});
|
|
420
|
-
if (type === "B3") {
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
672
|
+
if (type === "B3" && data[1] === "B3 TO DATA REQ ") {
|
|
673
|
+
const info = data[2].split(" ");
|
|
674
|
+
ResultFormatter.departureAirport(decodeResult, info[1]);
|
|
675
|
+
ResultFormatter.arrivalAirport(decodeResult, info[2]);
|
|
676
|
+
decodeResult.raw.day_of_month = Number(info[3]);
|
|
677
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
678
|
+
ResultFormatter.arrivalRunway(decodeResult, info[5].slice(1));
|
|
679
|
+
decodeResult.remaining.text = data.slice(3).join("/");
|
|
680
|
+
} else if (type === "B3") {
|
|
681
|
+
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
682
|
+
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
683
|
+
decodeResult.raw.day_of_month = Number(header[2]);
|
|
684
|
+
ResultFormatter.arrivalRunway(decodeResult, header[3].slice(1));
|
|
685
|
+
if (header.length > 4) {
|
|
686
|
+
decodeResult.remaining.text = header.slice(4).join(" ");
|
|
431
687
|
}
|
|
688
|
+
} else if (type === "C3" && data[1] === "C3 GATE REQ ") {
|
|
689
|
+
const info = data[2].split(" ");
|
|
690
|
+
ResultFormatter.departureAirport(decodeResult, info[1]);
|
|
691
|
+
ResultFormatter.arrivalAirport(decodeResult, info[2]);
|
|
692
|
+
decodeResult.raw.day_of_month = Number(info[3]);
|
|
693
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
694
|
+
decodeResult.remaining.text = info.slice(5).join(" ");
|
|
695
|
+
} else if (type === "C3") {
|
|
696
|
+
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
697
|
+
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
698
|
+
} else if (type === "ET") {
|
|
699
|
+
const airports = data[2].split(" ");
|
|
700
|
+
ResultFormatter.departureAirport(decodeResult, airports[1]);
|
|
701
|
+
ResultFormatter.arrivalAirport(decodeResult, airports[2]);
|
|
702
|
+
decodeResult.raw.day_of_month = Number(airports[3]);
|
|
703
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(airports[4]));
|
|
704
|
+
const estimates = data[3].split(" ");
|
|
705
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(estimates[1] + "00"));
|
|
706
|
+
decodeResult.remaining.text = estimates[2];
|
|
432
707
|
} else {
|
|
433
|
-
|
|
708
|
+
if (options.debug) {
|
|
709
|
+
console.log(`Decoder: Unkown 5Z RDC format: ${message.text}`);
|
|
710
|
+
}
|
|
434
711
|
}
|
|
435
712
|
decodeResult.decoded = true;
|
|
436
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
713
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text ? "partial" : "full";
|
|
437
714
|
} else {
|
|
438
715
|
if (options.debug) {
|
|
439
716
|
console.log(`Decoder: Unknown 5Z message: ${message.text}`);
|
|
@@ -534,129 +811,6 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
534
811
|
}
|
|
535
812
|
};
|
|
536
813
|
|
|
537
|
-
// lib/DateTimeUtils.ts
|
|
538
|
-
var DateTimeUtils = class {
|
|
539
|
-
// Expects a four digit UTC time string (HHMM)
|
|
540
|
-
static UTCToString(UTCString) {
|
|
541
|
-
let utcDate = /* @__PURE__ */ new Date();
|
|
542
|
-
utcDate.setUTCHours(+UTCString.substr(0, 2), +UTCString.substr(2, 2), 0);
|
|
543
|
-
return utcDate.toTimeString();
|
|
544
|
-
}
|
|
545
|
-
// Expects a six digit date string and a four digit UTC time string
|
|
546
|
-
// (DDMMYY) (HHMM)
|
|
547
|
-
static UTCDateTimeToString(dateString, timeString) {
|
|
548
|
-
let utcDate = /* @__PURE__ */ new Date();
|
|
549
|
-
utcDate.setUTCDate(+dateString.substr(0, 2));
|
|
550
|
-
utcDate.setUTCMonth(+dateString.substr(2, 2));
|
|
551
|
-
if (dateString.length === 6) {
|
|
552
|
-
utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
|
|
553
|
-
}
|
|
554
|
-
if (timeString.length === 6) {
|
|
555
|
-
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), +timeString.substr(4, 2));
|
|
556
|
-
} else {
|
|
557
|
-
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), 0);
|
|
558
|
-
}
|
|
559
|
-
return utcDate.toUTCString();
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
*
|
|
563
|
-
* @param time HHMMSS
|
|
564
|
-
* @returns seconds since midnight
|
|
565
|
-
*/
|
|
566
|
-
static convertHHMMSSToTod(time) {
|
|
567
|
-
const h = Number(time.substring(0, 2));
|
|
568
|
-
const m = Number(time.substring(2, 4));
|
|
569
|
-
const s = Number(time.substring(4, 6));
|
|
570
|
-
const tod = h * 3600 + m * 60 + s;
|
|
571
|
-
return tod;
|
|
572
|
-
}
|
|
573
|
-
/**
|
|
574
|
-
*
|
|
575
|
-
* @param time HHMMSS
|
|
576
|
-
* @param date MMDDYY or MMDDYYYY
|
|
577
|
-
* @returns seconds since epoch
|
|
578
|
-
*/
|
|
579
|
-
static convertDateTimeToEpoch(time, date) {
|
|
580
|
-
if (date.length === 6) {
|
|
581
|
-
date = date.substring(0, 4) + `20${date.substring(4, 6)}`;
|
|
582
|
-
}
|
|
583
|
-
const timestamp = `${date.substring(4, 8)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
|
|
584
|
-
const millis = Date.parse(timestamp);
|
|
585
|
-
return millis / 1e3;
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
|
|
589
|
-
// lib/utils/route_utils.ts
|
|
590
|
-
var RouteUtils = class _RouteUtils {
|
|
591
|
-
static routeToString(route) {
|
|
592
|
-
let str = "";
|
|
593
|
-
if (route.name) {
|
|
594
|
-
str += route.name;
|
|
595
|
-
}
|
|
596
|
-
if (route.runway) {
|
|
597
|
-
str += `(${route.runway})`;
|
|
598
|
-
}
|
|
599
|
-
if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
|
|
600
|
-
str += " starting at ";
|
|
601
|
-
} else if (str.length !== 0 && route.waypoints) {
|
|
602
|
-
str += ": ";
|
|
603
|
-
}
|
|
604
|
-
if (route.waypoints) {
|
|
605
|
-
str += _RouteUtils.waypointsToString(route.waypoints);
|
|
606
|
-
}
|
|
607
|
-
return str;
|
|
608
|
-
}
|
|
609
|
-
static waypointToString(waypoint) {
|
|
610
|
-
let s = waypoint.name;
|
|
611
|
-
if (waypoint.latitude && waypoint.longitude) {
|
|
612
|
-
s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
|
|
613
|
-
}
|
|
614
|
-
if (waypoint.offset) {
|
|
615
|
-
s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
|
|
616
|
-
}
|
|
617
|
-
if (waypoint.time && waypoint.timeFormat) {
|
|
618
|
-
s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
|
|
619
|
-
}
|
|
620
|
-
return s;
|
|
621
|
-
}
|
|
622
|
-
static getWaypoint(leg) {
|
|
623
|
-
const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
|
|
624
|
-
if (regex?.length == 4) {
|
|
625
|
-
return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
|
|
626
|
-
}
|
|
627
|
-
const waypoint = leg.split(",");
|
|
628
|
-
if (waypoint.length == 2) {
|
|
629
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
630
|
-
if (position) {
|
|
631
|
-
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
if (leg.length == 13 || leg.length == 14) {
|
|
635
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
636
|
-
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
637
|
-
if (position) {
|
|
638
|
-
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
return { name: leg };
|
|
642
|
-
}
|
|
643
|
-
// move out if we want public
|
|
644
|
-
static timestampToString(time, format) {
|
|
645
|
-
const date = new Date(time * 1e3);
|
|
646
|
-
if (format == "tod") {
|
|
647
|
-
return date.toISOString().slice(11, 19);
|
|
648
|
-
}
|
|
649
|
-
return date.toISOString().slice(0, -5) + "Z";
|
|
650
|
-
}
|
|
651
|
-
static waypointsToString(waypoints) {
|
|
652
|
-
let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
|
|
653
|
-
if (str.startsWith(" > ")) {
|
|
654
|
-
str = ">>" + str.slice(2);
|
|
655
|
-
}
|
|
656
|
-
return str;
|
|
657
|
-
}
|
|
658
|
-
};
|
|
659
|
-
|
|
660
814
|
// lib/plugins/Label_10_Slash.ts
|
|
661
815
|
var Label_10_Slash = class extends DecoderPlugin {
|
|
662
816
|
// eslint-disable-line camelcase
|
|
@@ -692,7 +846,7 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
692
846
|
ResultFormatter.heading(decodeResult, Number(parts[5]));
|
|
693
847
|
ResultFormatter.altitude(decodeResult, 100 * Number(parts[6]));
|
|
694
848
|
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
695
|
-
ResultFormatter.eta(decodeResult, parts[8] + "00");
|
|
849
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[8] + "00"));
|
|
696
850
|
const waypoints = [{
|
|
697
851
|
name: parts[11]
|
|
698
852
|
}, {
|
|
@@ -1026,28 +1180,12 @@ var Label_1M_Slash = class extends DecoderPlugin {
|
|
|
1026
1180
|
console.log(results);
|
|
1027
1181
|
}
|
|
1028
1182
|
decodeResult.raw.flight_number = results[0];
|
|
1029
|
-
decodeResult
|
|
1030
|
-
decodeResult
|
|
1031
|
-
decodeResult
|
|
1032
|
-
decodeResult
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
code: "ETA",
|
|
1036
|
-
label: "Estimated Time of Arrival",
|
|
1037
|
-
value: DateTimeUtils.UTCDateTimeToString(results[2], results[7])
|
|
1038
|
-
});
|
|
1039
|
-
decodeResult.formatted.items.push({
|
|
1040
|
-
type: "destination",
|
|
1041
|
-
code: "DST",
|
|
1042
|
-
label: "Destination",
|
|
1043
|
-
value: decodeResult.raw.arrival_icao
|
|
1044
|
-
});
|
|
1045
|
-
decodeResult.formatted.items.push({
|
|
1046
|
-
type: "origin",
|
|
1047
|
-
code: "ORG",
|
|
1048
|
-
label: "Origin",
|
|
1049
|
-
value: decodeResult.raw.departure_icao
|
|
1050
|
-
});
|
|
1183
|
+
ResultFormatter.departureAirport(decodeResult, results[3]);
|
|
1184
|
+
ResultFormatter.arrivalAirport(decodeResult, results[4]);
|
|
1185
|
+
ResultFormatter.alternateAirport(decodeResult, results[5]);
|
|
1186
|
+
ResultFormatter.arrivalRunway(decodeResult, results[8].replace(results[4], ""));
|
|
1187
|
+
const yymmdd = results[2];
|
|
1188
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertDateTimeToEpoch(results[7] + "00", yymmdd.substring(2, 4) + yymmdd.substring(4, 6) + yymmdd.substring(0, 2)), "epoch");
|
|
1051
1189
|
}
|
|
1052
1190
|
decodeResult.decoded = true;
|
|
1053
1191
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1134,15 +1272,15 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
1134
1272
|
const fields = content.split(",");
|
|
1135
1273
|
if (fields.length == 9) {
|
|
1136
1274
|
processPosition(decodeResult, fields[0].trim());
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1275
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
|
|
1276
|
+
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
1277
|
+
ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
|
|
1278
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[7]));
|
|
1279
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[8]);
|
|
1140
1280
|
decodeResult.remaining.text = [
|
|
1141
1281
|
fields[1],
|
|
1142
|
-
fields[2],
|
|
1143
1282
|
fields[4],
|
|
1144
|
-
fields[5]
|
|
1145
|
-
fields[7]
|
|
1283
|
+
fields[5]
|
|
1146
1284
|
].join(",");
|
|
1147
1285
|
decodeResult.decoded = true;
|
|
1148
1286
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1158,7 +1296,7 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
1158
1296
|
};
|
|
1159
1297
|
function processPosition(decodeResult, value) {
|
|
1160
1298
|
if (value.length !== 16 && value[0] !== "N" && value[0] !== "S" && value[8] !== "W" && value[8] !== "E") {
|
|
1161
|
-
return
|
|
1299
|
+
return;
|
|
1162
1300
|
}
|
|
1163
1301
|
const latDir = value[0] === "N" ? 1 : -1;
|
|
1164
1302
|
const lonDir = value[8] === "E" ? 1 : -1;
|
|
@@ -1166,45 +1304,52 @@ function processPosition(decodeResult, value) {
|
|
|
1166
1304
|
latitude: latDir * Number(value.substring(1, 7)),
|
|
1167
1305
|
longitude: lonDir * Number(value.substring(9, 15))
|
|
1168
1306
|
};
|
|
1169
|
-
|
|
1170
|
-
decodeResult.raw.position = position;
|
|
1171
|
-
decodeResult.formatted.items.push({
|
|
1172
|
-
type: "aircraft_position",
|
|
1173
|
-
code: "POS",
|
|
1174
|
-
label: "Aircraft Position",
|
|
1175
|
-
value: CoordinateUtils.coordinateString(position)
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
return !!position;
|
|
1179
|
-
}
|
|
1180
|
-
function processAlt(decodeResult, value) {
|
|
1181
|
-
decodeResult.raw.altitude = Number(value);
|
|
1182
|
-
decodeResult.formatted.items.push({
|
|
1183
|
-
type: "altitude",
|
|
1184
|
-
code: "ALT",
|
|
1185
|
-
label: "Altitude",
|
|
1186
|
-
value: `${decodeResult.raw.altitude} feet`
|
|
1187
|
-
});
|
|
1188
|
-
}
|
|
1189
|
-
function processTemp(decodeResult, value) {
|
|
1190
|
-
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1191
|
-
decodeResult.formatted.items.push({
|
|
1192
|
-
type: "outside_air_temperature",
|
|
1193
|
-
code: "OATEMP",
|
|
1194
|
-
label: "Outside Air Temperature (C)",
|
|
1195
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1196
|
-
});
|
|
1197
|
-
}
|
|
1198
|
-
function processArrvApt(decodeResult, value) {
|
|
1199
|
-
decodeResult.raw.arrival_icao = value;
|
|
1200
|
-
decodeResult.formatted.items.push({
|
|
1201
|
-
type: "destination",
|
|
1202
|
-
code: "DST",
|
|
1203
|
-
label: "Destination",
|
|
1204
|
-
value: decodeResult.raw.arrival_icao
|
|
1205
|
-
});
|
|
1307
|
+
ResultFormatter.position(decodeResult, position);
|
|
1206
1308
|
}
|
|
1207
1309
|
|
|
1310
|
+
// lib/plugins/Label_24_Slash.ts
|
|
1311
|
+
var Label_24_Slash = class extends DecoderPlugin {
|
|
1312
|
+
name = "label-24-slash";
|
|
1313
|
+
qualifiers() {
|
|
1314
|
+
return {
|
|
1315
|
+
labels: ["24"],
|
|
1316
|
+
preambles: ["/"]
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
decode(message, options = {}) {
|
|
1320
|
+
const decodeResult = this.defaultResult();
|
|
1321
|
+
decodeResult.decoder.name = this.name;
|
|
1322
|
+
decodeResult.formatted.description = "Position Report";
|
|
1323
|
+
decodeResult.message = message;
|
|
1324
|
+
const fields = message.text.split("/");
|
|
1325
|
+
if (fields.length == 10 && fields[0] == "" && fields[9] == "") {
|
|
1326
|
+
const mmddyy = fields[1].substring(4, 6) + fields[1].substring(2, 4) + fields[1].substring(0, 2);
|
|
1327
|
+
const hhmmss = fields[2] + "00";
|
|
1328
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(hhmmss, mmddyy);
|
|
1329
|
+
ResultFormatter.flightNumber(decodeResult, fields[3]);
|
|
1330
|
+
ResultFormatter.altitude(decodeResult, Number(fields[4]));
|
|
1331
|
+
const lat = fields[5];
|
|
1332
|
+
const lon = fields[6];
|
|
1333
|
+
const position = {
|
|
1334
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
|
|
1335
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
|
|
1336
|
+
};
|
|
1337
|
+
ResultFormatter.position(decodeResult, position);
|
|
1338
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[8] + "00"));
|
|
1339
|
+
decodeResult.remaining.text = fields[7];
|
|
1340
|
+
decodeResult.decoded = true;
|
|
1341
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1342
|
+
} else {
|
|
1343
|
+
if (options.debug) {
|
|
1344
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`);
|
|
1345
|
+
}
|
|
1346
|
+
decodeResult.decoded = false;
|
|
1347
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1348
|
+
}
|
|
1349
|
+
return decodeResult;
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1208
1353
|
// lib/plugins/Label_30_Slash_EA.ts
|
|
1209
1354
|
var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
1210
1355
|
name = "label-30-slash-ea";
|
|
@@ -1219,27 +1364,16 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
|
1219
1364
|
decodeResult.decoder.name = this.name;
|
|
1220
1365
|
decodeResult.formatted.description = "ETA Report";
|
|
1221
1366
|
decodeResult.message = message;
|
|
1222
|
-
const results = message.text.split(/\n|\//).slice(1);
|
|
1223
|
-
if (results) {
|
|
1224
|
-
if (options.debug) {
|
|
1225
|
-
console.log(`Label 30 EA: results`);
|
|
1226
|
-
console.log(results);
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
decodeResult.
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
label: "Estimated Time of Arrival",
|
|
1233
|
-
value: DateTimeUtils.UTCToString(results[0].substr(2, 4))
|
|
1234
|
-
});
|
|
1235
|
-
if (results[1].substr(0, 2) === "DS") {
|
|
1236
|
-
decodeResult.raw.arrival_icao = results[1].substr(2, 4);
|
|
1237
|
-
decodeResult.formatted.items.push({
|
|
1238
|
-
type: "destination",
|
|
1239
|
-
code: "DST",
|
|
1240
|
-
label: "Destination",
|
|
1241
|
-
value: decodeResult.raw.arrival_icao
|
|
1242
|
-
});
|
|
1367
|
+
const results = message.text.split(/\n|\//).slice(1);
|
|
1368
|
+
if (results) {
|
|
1369
|
+
if (options.debug) {
|
|
1370
|
+
console.log(`Label 30 EA: results`);
|
|
1371
|
+
console.log(results);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4) + "00"));
|
|
1375
|
+
if (results[1].substring(0, 2) === "DS") {
|
|
1376
|
+
ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6));
|
|
1243
1377
|
decodeResult.remaining.text = "/".concat(results[2]);
|
|
1244
1378
|
} else {
|
|
1245
1379
|
decodeResult.remaining.text = "/".concat(results[1], "/", results[2]);
|
|
@@ -1531,6 +1665,221 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
1531
1665
|
}
|
|
1532
1666
|
};
|
|
1533
1667
|
|
|
1668
|
+
// lib/plugins/Label_4A.ts
|
|
1669
|
+
var Label_4A = class extends DecoderPlugin {
|
|
1670
|
+
name = "label-4a";
|
|
1671
|
+
qualifiers() {
|
|
1672
|
+
return {
|
|
1673
|
+
labels: ["4A"]
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
decode(message, options = {}) {
|
|
1677
|
+
const decodeResult = this.defaultResult();
|
|
1678
|
+
decodeResult.decoder.name = this.name;
|
|
1679
|
+
decodeResult.message = message;
|
|
1680
|
+
decodeResult.formatted.description = "Latest New Format";
|
|
1681
|
+
let text2 = message.text;
|
|
1682
|
+
if (text2.match(/^M\d{2}A\w{6}/)) {
|
|
1683
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
1684
|
+
text2 = text2.substring(10);
|
|
1685
|
+
}
|
|
1686
|
+
decodeResult.decoded = true;
|
|
1687
|
+
const fields = text2.split(",");
|
|
1688
|
+
if (fields.length === 11) {
|
|
1689
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1690
|
+
ResultFormatter.tail(decodeResult, fields[2].replace(".", ""));
|
|
1691
|
+
if (fields[3])
|
|
1692
|
+
ResultFormatter.callsign(decodeResult, fields[3]);
|
|
1693
|
+
ResultFormatter.departureAirport(decodeResult, fields[4]);
|
|
1694
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[5]);
|
|
1695
|
+
ResultFormatter.altitude(decodeResult, text2.substring(48, 51) * 100);
|
|
1696
|
+
decodeResult.remaining.text = fields.slice(8).join(",");
|
|
1697
|
+
} else if (fields.length === 6) {
|
|
1698
|
+
if (fields[0].match(/^[NS]/)) {
|
|
1699
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13)));
|
|
1700
|
+
let wp1 = {
|
|
1701
|
+
name: fields[0].substring(13).trim(),
|
|
1702
|
+
time: DateTimeUtils.convertHHMMSSToTod(fields[1].substring(0, 6)),
|
|
1703
|
+
timeFormat: "tod"
|
|
1704
|
+
};
|
|
1705
|
+
ResultFormatter.altitude(decodeResult, fields[1].substring(6, 9) * 100);
|
|
1706
|
+
let wp2 = {
|
|
1707
|
+
name: fields[1].substring(9).trim(),
|
|
1708
|
+
time: DateTimeUtils.convertHHMMSSToTod(fields[2]),
|
|
1709
|
+
timeFormat: "tod"
|
|
1710
|
+
};
|
|
1711
|
+
decodeResult.raw.route = { waypoints: [wp1, wp2] };
|
|
1712
|
+
decodeResult.formatted.items.push({
|
|
1713
|
+
type: "aircraft_route",
|
|
1714
|
+
code: "ROUTE",
|
|
1715
|
+
label: "Aircraft Route",
|
|
1716
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1717
|
+
});
|
|
1718
|
+
ResultFormatter.temperature(decodeResult, fields[3]);
|
|
1719
|
+
decodeResult.remaining.text = fields.slice(4).join(",");
|
|
1720
|
+
} else {
|
|
1721
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1722
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1]));
|
|
1723
|
+
decodeResult.remaining.text = fields[2];
|
|
1724
|
+
ResultFormatter.altitude(decodeResult, fields[3]);
|
|
1725
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates((fields[4] + fields[5]).replace(/[ \.]/g, "")));
|
|
1726
|
+
}
|
|
1727
|
+
} else {
|
|
1728
|
+
decodeResult.decoded = false;
|
|
1729
|
+
decodeResult.remaining.text = text2;
|
|
1730
|
+
}
|
|
1731
|
+
if (decodeResult.decoded) {
|
|
1732
|
+
if (!decodeResult.remaining.text)
|
|
1733
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1734
|
+
else
|
|
1735
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1736
|
+
} else {
|
|
1737
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1738
|
+
}
|
|
1739
|
+
return decodeResult;
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
// lib/plugins/Label_4A_01.ts
|
|
1744
|
+
var Label_4A_01 = class extends DecoderPlugin {
|
|
1745
|
+
name = "label-4a-01";
|
|
1746
|
+
qualifiers() {
|
|
1747
|
+
return {
|
|
1748
|
+
labels: ["4A"],
|
|
1749
|
+
preambles: ["01"]
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
decode(message, options = {}) {
|
|
1753
|
+
const decodeResult = this.defaultResult();
|
|
1754
|
+
decodeResult.decoder.name = this.name;
|
|
1755
|
+
decodeResult.message = message;
|
|
1756
|
+
decodeResult.formatted.description = "Latest New Format";
|
|
1757
|
+
decodeResult.decoded = true;
|
|
1758
|
+
let rgx = message.text.match(/^01([A-Z]{2})([A-Z]{2})\s*(\w+)\/(\d{6})([A-Z]{4})([A-Z]{4})\r\n([+-]\s*\d+)(\d{3}\.\d)([+-]\s*\d+\.\d)/);
|
|
1759
|
+
if (rgx) {
|
|
1760
|
+
ResultFormatter.state_change(decodeResult, rgx[1], rgx[2]);
|
|
1761
|
+
ResultFormatter.callsign(decodeResult, rgx[3]);
|
|
1762
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(rgx[4] + "00"));
|
|
1763
|
+
ResultFormatter.departureAirport(decodeResult, rgx[5]);
|
|
1764
|
+
ResultFormatter.arrivalAirport(decodeResult, rgx[6]);
|
|
1765
|
+
ResultFormatter.altitude(decodeResult, Number(rgx[7].replace(/ /g, "")));
|
|
1766
|
+
decodeResult.remaining.text = rgx[8];
|
|
1767
|
+
ResultFormatter.temperature(decodeResult, rgx[9].replace(/ /g, ""));
|
|
1768
|
+
} else {
|
|
1769
|
+
decodeResult.decoded = false;
|
|
1770
|
+
decodeResult.remaining.text = message.text;
|
|
1771
|
+
}
|
|
1772
|
+
if (decodeResult.decoded) {
|
|
1773
|
+
if (!decodeResult.remaining.text)
|
|
1774
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1775
|
+
else
|
|
1776
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1777
|
+
} else {
|
|
1778
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1779
|
+
}
|
|
1780
|
+
return decodeResult;
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
// lib/plugins/Label_4A_DIS.ts
|
|
1785
|
+
var Label_4A_DIS = class extends DecoderPlugin {
|
|
1786
|
+
name = "label-4a-dis";
|
|
1787
|
+
qualifiers() {
|
|
1788
|
+
return {
|
|
1789
|
+
labels: ["4A"],
|
|
1790
|
+
preambles: ["DIS"]
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
decode(message, options = {}) {
|
|
1794
|
+
const decodeResult = this.defaultResult();
|
|
1795
|
+
decodeResult.decoder.name = this.name;
|
|
1796
|
+
decodeResult.message = message;
|
|
1797
|
+
decodeResult.formatted.description = "Latest New Format";
|
|
1798
|
+
decodeResult.decoded = true;
|
|
1799
|
+
const fields = message.text.split(",");
|
|
1800
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(2) + "00"));
|
|
1801
|
+
ResultFormatter.callsign(decodeResult, fields[2]);
|
|
1802
|
+
ResultFormatter.freetext(decodeResult, fields.slice(3).join(""));
|
|
1803
|
+
if (decodeResult.decoded) {
|
|
1804
|
+
if (!decodeResult.remaining.text)
|
|
1805
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1806
|
+
else
|
|
1807
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1808
|
+
} else {
|
|
1809
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1810
|
+
}
|
|
1811
|
+
return decodeResult;
|
|
1812
|
+
}
|
|
1813
|
+
};
|
|
1814
|
+
|
|
1815
|
+
// lib/plugins/Label_4A_DOOR.ts
|
|
1816
|
+
var Label_4A_DOOR = class extends DecoderPlugin {
|
|
1817
|
+
name = "label-4a-door";
|
|
1818
|
+
qualifiers() {
|
|
1819
|
+
return {
|
|
1820
|
+
labels: ["4A"],
|
|
1821
|
+
preambles: ["DOOR"]
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
decode(message, options = {}) {
|
|
1825
|
+
const decodeResult = this.defaultResult();
|
|
1826
|
+
decodeResult.decoder.name = this.name;
|
|
1827
|
+
decodeResult.message = message;
|
|
1828
|
+
decodeResult.formatted.description = "Latest New Format";
|
|
1829
|
+
decodeResult.decoded = true;
|
|
1830
|
+
const fields = message.text.split(" ");
|
|
1831
|
+
if (fields.length === 3) {
|
|
1832
|
+
ResultFormatter.door_event(decodeResult, fields[0].split("/")[1], fields[1]);
|
|
1833
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2] + "00"));
|
|
1834
|
+
} else {
|
|
1835
|
+
decodeResult.decoded = false;
|
|
1836
|
+
decodeResult.remaining.text = text;
|
|
1837
|
+
}
|
|
1838
|
+
if (decodeResult.decoded) {
|
|
1839
|
+
if (!decodeResult.remaining.text)
|
|
1840
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1841
|
+
else
|
|
1842
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1843
|
+
} else {
|
|
1844
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1845
|
+
}
|
|
1846
|
+
return decodeResult;
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
|
|
1850
|
+
// lib/plugins/Label_4A_Slash_01.ts
|
|
1851
|
+
var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
1852
|
+
name = "label-4a-slash-01";
|
|
1853
|
+
qualifiers() {
|
|
1854
|
+
return {
|
|
1855
|
+
labels: ["4A"],
|
|
1856
|
+
preambles: ["/01"]
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
decode(message, options = {}) {
|
|
1860
|
+
const decodeResult = this.defaultResult();
|
|
1861
|
+
decodeResult.decoder.name = this.name;
|
|
1862
|
+
decodeResult.message = message;
|
|
1863
|
+
decodeResult.formatted.description = "Latest New Format";
|
|
1864
|
+
decodeResult.decoded = true;
|
|
1865
|
+
if (message.text.length === 5 && message.text.substring(0, 4) === "/01-") {
|
|
1866
|
+
decodeResult.remaining.text = message.text.substring(4);
|
|
1867
|
+
} else {
|
|
1868
|
+
decodeResult.decoded = false;
|
|
1869
|
+
decodeResult.remaining.text = message.text;
|
|
1870
|
+
}
|
|
1871
|
+
if (decodeResult.decoded) {
|
|
1872
|
+
if (!decodeResult.remaining.text)
|
|
1873
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1874
|
+
else
|
|
1875
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1876
|
+
} else {
|
|
1877
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1878
|
+
}
|
|
1879
|
+
return decodeResult;
|
|
1880
|
+
}
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1534
1883
|
// lib/plugins/Label_4N.ts
|
|
1535
1884
|
var Label_4N = class extends DecoderPlugin {
|
|
1536
1885
|
name = "label-4n";
|
|
@@ -1544,20 +1893,20 @@ var Label_4N = class extends DecoderPlugin {
|
|
|
1544
1893
|
decodeResult.decoder.name = this.name;
|
|
1545
1894
|
decodeResult.message = message;
|
|
1546
1895
|
decodeResult.formatted.description = "Airline Defined";
|
|
1547
|
-
let
|
|
1548
|
-
if (
|
|
1896
|
+
let text2 = message.text;
|
|
1897
|
+
if (text2.match(/^M\d{2}A\w{6}/)) {
|
|
1549
1898
|
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
1550
|
-
|
|
1899
|
+
text2 = text2.substring(10);
|
|
1551
1900
|
}
|
|
1552
1901
|
decodeResult.decoded = true;
|
|
1553
|
-
const fields =
|
|
1554
|
-
if (
|
|
1555
|
-
decodeResult.raw.day_of_month =
|
|
1556
|
-
ResultFormatter.departureAirport(decodeResult,
|
|
1557
|
-
ResultFormatter.arrivalAirport(decodeResult,
|
|
1558
|
-
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
1559
|
-
ResultFormatter.altitude(decodeResult,
|
|
1560
|
-
decodeResult.remaining.text = [
|
|
1902
|
+
const fields = text2.split(",");
|
|
1903
|
+
if (text2.length === 51) {
|
|
1904
|
+
decodeResult.raw.day_of_month = text2.substring(0, 2);
|
|
1905
|
+
ResultFormatter.departureAirport(decodeResult, text2.substring(8, 11));
|
|
1906
|
+
ResultFormatter.arrivalAirport(decodeResult, text2.substring(13, 16));
|
|
1907
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text2.substring(30, 45).replace(/^(.)0/, "$1")));
|
|
1908
|
+
ResultFormatter.altitude(decodeResult, text2.substring(48, 51) * 100);
|
|
1909
|
+
decodeResult.remaining.text = [text2.substring(2, 4), text2.substring(19, 29)].join(" ");
|
|
1561
1910
|
} else if (fields.length === 33) {
|
|
1562
1911
|
decodeResult.raw.date = fields[3];
|
|
1563
1912
|
if (fields[1] === "B") {
|
|
@@ -1575,10 +1924,10 @@ var Label_4N = class extends DecoderPlugin {
|
|
|
1575
1924
|
decodeResult.remaining.text = [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter((f) => f != "").join(",");
|
|
1576
1925
|
} else {
|
|
1577
1926
|
decodeResult.decoded = false;
|
|
1578
|
-
decodeResult.remaining.text =
|
|
1927
|
+
decodeResult.remaining.text = text2;
|
|
1579
1928
|
}
|
|
1580
1929
|
if (decodeResult.decoded) {
|
|
1581
|
-
if (decodeResult.remaining.text
|
|
1930
|
+
if (!decodeResult.remaining.text)
|
|
1582
1931
|
decodeResult.decoder.decodeLevel = "full";
|
|
1583
1932
|
else
|
|
1584
1933
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1766,14 +2115,14 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
1766
2115
|
decodeResult.decoder.name = this.name;
|
|
1767
2116
|
decodeResult.message = message;
|
|
1768
2117
|
decodeResult.formatted.description = "Airline Defined";
|
|
1769
|
-
let
|
|
1770
|
-
if (
|
|
2118
|
+
let text2 = message.text;
|
|
2119
|
+
if (text2.match(/^M\d{2}A\w{6}/)) {
|
|
1771
2120
|
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
1772
|
-
|
|
2121
|
+
text2 = text2.substring(10);
|
|
1773
2122
|
}
|
|
1774
2123
|
decodeResult.decoded = true;
|
|
1775
|
-
if (
|
|
1776
|
-
const fields =
|
|
2124
|
+
if (text2.substring(0, 10) === "4DH3 ETAT2") {
|
|
2125
|
+
const fields = text2.split(/\s+/);
|
|
1777
2126
|
if (fields[2].length > 5) {
|
|
1778
2127
|
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
1779
2128
|
}
|
|
@@ -1782,14 +2131,17 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
1782
2131
|
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
1783
2132
|
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
1784
2133
|
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
1785
|
-
ResultFormatter.eta(decodeResult, fields[6] + "00");
|
|
1786
|
-
} else if (
|
|
1787
|
-
decodeResult.raw.day_of_month =
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
2134
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2135
|
+
} else if (text2.substring(0, 5) === "001PR") {
|
|
2136
|
+
decodeResult.raw.day_of_month = text2.substring(5, 7);
|
|
2137
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text2.substring(13, 28).replace(/\./g, ""));
|
|
2138
|
+
if (position) {
|
|
2139
|
+
ResultFormatter.position(decodeResult, position);
|
|
2140
|
+
}
|
|
2141
|
+
ResultFormatter.altitude(decodeResult, Number(text2.substring(28, 33)));
|
|
2142
|
+
decodeResult.remaining.text = text2.substring(33);
|
|
1791
2143
|
} else {
|
|
1792
|
-
const fields =
|
|
2144
|
+
const fields = text2.replace(/\s/g, "").split(",");
|
|
1793
2145
|
if (fields.length === 9) {
|
|
1794
2146
|
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
1795
2147
|
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
@@ -1802,7 +2154,7 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
1802
2154
|
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
1803
2155
|
}
|
|
1804
2156
|
);
|
|
1805
|
-
ResultFormatter.altitude(decodeResult, fields[5]);
|
|
2157
|
+
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
1806
2158
|
ResultFormatter.groundspeed(decodeResult, fields[6]);
|
|
1807
2159
|
ResultFormatter.heading(decodeResult, fields[7]);
|
|
1808
2160
|
decodeResult.remaining.text = fields[8];
|
|
@@ -1812,7 +2164,7 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
1812
2164
|
}
|
|
1813
2165
|
}
|
|
1814
2166
|
if (decodeResult.decoded) {
|
|
1815
|
-
if (decodeResult.remaining.text
|
|
2167
|
+
if (!decodeResult.remaining.text)
|
|
1816
2168
|
decodeResult.decoder.decodeLevel = "full";
|
|
1817
2169
|
else
|
|
1818
2170
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1843,19 +2195,8 @@ var Label_8E = class extends DecoderPlugin {
|
|
|
1843
2195
|
console.log(`Label 8E ETA: groups`);
|
|
1844
2196
|
console.log(results.groups);
|
|
1845
2197
|
}
|
|
1846
|
-
decodeResult.
|
|
1847
|
-
|
|
1848
|
-
code: "ETA",
|
|
1849
|
-
label: "Estimated Time of Arrival",
|
|
1850
|
-
value: DateTimeUtils.UTCToString(results.groups.arrival_eta)
|
|
1851
|
-
});
|
|
1852
|
-
decodeResult.raw.arrival_icao = results.groups.arrival_icao;
|
|
1853
|
-
decodeResult.formatted.items.push({
|
|
1854
|
-
type: "destination",
|
|
1855
|
-
code: "DST",
|
|
1856
|
-
label: "Destination",
|
|
1857
|
-
value: decodeResult.raw.arrival_icao
|
|
1858
|
-
});
|
|
2198
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2199
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1859
2200
|
}
|
|
1860
2201
|
decodeResult.decoded = true;
|
|
1861
2202
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1908,44 +2249,158 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
1908
2249
|
}
|
|
1909
2250
|
};
|
|
1910
2251
|
|
|
1911
|
-
// lib/plugins/Label_H1_FLR.ts
|
|
1912
|
-
var Label_H1_FLR = class extends DecoderPlugin {
|
|
1913
|
-
name = "label-h1-flr";
|
|
2252
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
2253
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
2254
|
+
name = "label-h1-flr";
|
|
2255
|
+
qualifiers() {
|
|
2256
|
+
return {
|
|
2257
|
+
labels: ["H1"],
|
|
2258
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
decode(message, options = {}) {
|
|
2262
|
+
let decodeResult = this.defaultResult();
|
|
2263
|
+
decodeResult.decoder.name = this.name;
|
|
2264
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
2265
|
+
decodeResult.message = message;
|
|
2266
|
+
const parts = message.text.split("/FR");
|
|
2267
|
+
if (parts.length > 1) {
|
|
2268
|
+
decodeResult.remaining.text = "";
|
|
2269
|
+
const fields = parts[0].split("/");
|
|
2270
|
+
for (let i = 1; i < fields.length; i++) {
|
|
2271
|
+
const field = fields[i];
|
|
2272
|
+
if (field.startsWith("PN")) {
|
|
2273
|
+
processUnknown(decodeResult, "/" + field);
|
|
2274
|
+
} else {
|
|
2275
|
+
processUnknown(decodeResult, "/" + field);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
const data = parts[1].substring(0, 20);
|
|
2279
|
+
const msg = parts[1].substring(20);
|
|
2280
|
+
const datetime = data.substring(0, 12);
|
|
2281
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2282
|
+
processUnknown(decodeResult, data.substring(12));
|
|
2283
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2284
|
+
decodeResult.raw.fault_message = msg;
|
|
2285
|
+
decodeResult.formatted.items.push({
|
|
2286
|
+
type: "fault",
|
|
2287
|
+
code: "FR",
|
|
2288
|
+
label: "Fault Report",
|
|
2289
|
+
value: decodeResult.raw.fault_message
|
|
2290
|
+
});
|
|
2291
|
+
decodeResult.decoded = true;
|
|
2292
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2293
|
+
} else {
|
|
2294
|
+
if (options.debug) {
|
|
2295
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2296
|
+
}
|
|
2297
|
+
decodeResult.remaining.text = message.text;
|
|
2298
|
+
decodeResult.decoded = false;
|
|
2299
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2300
|
+
}
|
|
2301
|
+
return decodeResult;
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
function processUnknown(decodeResult, value) {
|
|
2305
|
+
decodeResult.remaining.text += value;
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
// lib/plugins/Label_H1_OHMA.ts
|
|
2309
|
+
var zlib = __toESM(require("minizlib"));
|
|
2310
|
+
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
2311
|
+
name = "label-h1-ohma";
|
|
2312
|
+
qualifiers() {
|
|
2313
|
+
return {
|
|
2314
|
+
labels: ["H1"],
|
|
2315
|
+
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
2316
|
+
};
|
|
2317
|
+
}
|
|
2318
|
+
decode(message, options = {}) {
|
|
2319
|
+
let decodeResult = this.defaultResult();
|
|
2320
|
+
decodeResult.decoder.name = this.name;
|
|
2321
|
+
decodeResult.formatted.description = "OHMA Message";
|
|
2322
|
+
decodeResult.message = message;
|
|
2323
|
+
decodeResult.remaining.text = "";
|
|
2324
|
+
const data = message.text.split("OHMA")[1];
|
|
2325
|
+
try {
|
|
2326
|
+
const compressedBuffer = Buffer.from(data, "base64");
|
|
2327
|
+
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
2328
|
+
decompress.write(compressedBuffer);
|
|
2329
|
+
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
2330
|
+
const result = decompress.read();
|
|
2331
|
+
const jsonText = result.toString();
|
|
2332
|
+
let formattedMsg;
|
|
2333
|
+
let jsonMessage;
|
|
2334
|
+
try {
|
|
2335
|
+
jsonMessage = JSON.parse(jsonText).message;
|
|
2336
|
+
} catch {
|
|
2337
|
+
jsonMessage = jsonText;
|
|
2338
|
+
}
|
|
2339
|
+
try {
|
|
2340
|
+
const ohmaMsg = JSON.parse(jsonMessage);
|
|
2341
|
+
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
2342
|
+
} catch {
|
|
2343
|
+
formattedMsg = jsonMessage;
|
|
2344
|
+
}
|
|
2345
|
+
decodeResult.decoded = true;
|
|
2346
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2347
|
+
decodeResult.raw.ohma = jsonText;
|
|
2348
|
+
decodeResult.formatted.items.push({
|
|
2349
|
+
type: "ohma",
|
|
2350
|
+
code: "OHMA",
|
|
2351
|
+
label: "OHMA Downlink",
|
|
2352
|
+
value: formattedMsg
|
|
2353
|
+
});
|
|
2354
|
+
} catch (e) {
|
|
2355
|
+
if (options.debug) {
|
|
2356
|
+
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
2357
|
+
}
|
|
2358
|
+
decodeResult.remaining.text += message.text;
|
|
2359
|
+
decodeResult.decoded = false;
|
|
2360
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2361
|
+
}
|
|
2362
|
+
return decodeResult;
|
|
2363
|
+
}
|
|
2364
|
+
};
|
|
2365
|
+
|
|
2366
|
+
// lib/plugins/Label_H1_WRN.ts
|
|
2367
|
+
var Label_H1_WRN = class extends DecoderPlugin {
|
|
2368
|
+
name = "label-h1-wrn";
|
|
1914
2369
|
qualifiers() {
|
|
1915
2370
|
return {
|
|
1916
2371
|
labels: ["H1"],
|
|
1917
|
-
preambles: ["
|
|
2372
|
+
preambles: ["WRN", "#CFBWRN"]
|
|
1918
2373
|
};
|
|
1919
2374
|
}
|
|
1920
2375
|
decode(message, options = {}) {
|
|
1921
2376
|
let decodeResult = this.defaultResult();
|
|
1922
2377
|
decodeResult.decoder.name = this.name;
|
|
1923
|
-
decodeResult.formatted.description = "
|
|
2378
|
+
decodeResult.formatted.description = "Warning Message";
|
|
1924
2379
|
decodeResult.message = message;
|
|
1925
|
-
const parts = message.text.split("/
|
|
2380
|
+
const parts = message.text.split("/WN");
|
|
1926
2381
|
if (parts.length > 1) {
|
|
1927
2382
|
decodeResult.remaining.text = "";
|
|
1928
2383
|
const fields = parts[0].split("/");
|
|
1929
2384
|
for (let i = 1; i < fields.length; i++) {
|
|
1930
2385
|
const field = fields[i];
|
|
1931
2386
|
if (field.startsWith("PN")) {
|
|
1932
|
-
|
|
2387
|
+
processUnknown2(decodeResult, "/" + field);
|
|
1933
2388
|
} else {
|
|
1934
|
-
|
|
2389
|
+
processUnknown2(decodeResult, "/" + field);
|
|
1935
2390
|
}
|
|
1936
2391
|
}
|
|
1937
2392
|
const data = parts[1].substring(0, 20);
|
|
1938
2393
|
const msg = parts[1].substring(20);
|
|
1939
2394
|
const datetime = data.substring(0, 12);
|
|
1940
2395
|
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
1941
|
-
|
|
2396
|
+
processUnknown2(decodeResult, data.substring(12));
|
|
1942
2397
|
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
1943
|
-
decodeResult.raw.
|
|
2398
|
+
decodeResult.raw.warning_message = msg;
|
|
1944
2399
|
decodeResult.formatted.items.push({
|
|
1945
|
-
type: "
|
|
1946
|
-
code: "
|
|
1947
|
-
label: "
|
|
1948
|
-
value: decodeResult.raw.
|
|
2400
|
+
type: "warning",
|
|
2401
|
+
code: "WRN",
|
|
2402
|
+
label: "Warning Message",
|
|
2403
|
+
value: decodeResult.raw.warning_message
|
|
1949
2404
|
});
|
|
1950
2405
|
decodeResult.decoded = true;
|
|
1951
2406
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1960,7 +2415,7 @@ var Label_H1_FLR = class extends DecoderPlugin {
|
|
|
1960
2415
|
return decodeResult;
|
|
1961
2416
|
}
|
|
1962
2417
|
};
|
|
1963
|
-
function
|
|
2418
|
+
function processUnknown2(decodeResult, value) {
|
|
1964
2419
|
decodeResult.remaining.text += value;
|
|
1965
2420
|
}
|
|
1966
2421
|
|
|
@@ -2126,11 +2581,10 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
2126
2581
|
// lib/utils/h1_helper.ts
|
|
2127
2582
|
var H1Helper = class {
|
|
2128
2583
|
static decodeH1Message(decodeResult, message) {
|
|
2129
|
-
let allKnownFields = true;
|
|
2130
2584
|
const checksum = message.slice(-4);
|
|
2131
2585
|
const data = message.slice(0, message.length - 4);
|
|
2132
2586
|
const fields = data.split("/");
|
|
2133
|
-
|
|
2587
|
+
parseMessageType(decodeResult, fields[0]);
|
|
2134
2588
|
for (let i = 1; i < fields.length; ++i) {
|
|
2135
2589
|
if (fields[i].startsWith("FN")) {
|
|
2136
2590
|
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
@@ -2149,32 +2603,22 @@ var H1Helper = class {
|
|
|
2149
2603
|
decodeResult.raw.message_timestamp = time;
|
|
2150
2604
|
} else if (fields[i].startsWith("PS")) {
|
|
2151
2605
|
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2152
|
-
allKnownFields == allKnownFields && pos;
|
|
2153
2606
|
} else if (fields[i].startsWith("DT")) {
|
|
2154
2607
|
const data2 = fields[i].substring(2).split(",");
|
|
2155
|
-
|
|
2156
|
-
allKnownFields = allKnownFields && dt;
|
|
2608
|
+
processDT(decodeResult, data2);
|
|
2157
2609
|
} else if (fields[i].startsWith("ID")) {
|
|
2158
2610
|
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2159
2611
|
} else if (fields[i].startsWith("LR")) {
|
|
2160
2612
|
const data2 = fields[i].substring(2).split(",");
|
|
2161
|
-
|
|
2162
|
-
allKnownFields = allKnownFields && lr;
|
|
2613
|
+
processLR(decodeResult, data2);
|
|
2163
2614
|
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2164
|
-
|
|
2165
|
-
allKnownFields = allKnownFields && fp;
|
|
2615
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2166
2616
|
} else if (fields[i].startsWith("PR")) {
|
|
2167
|
-
allKnownFields = false;
|
|
2168
2617
|
decodeResult.remaining.text += "/" + fields[i];
|
|
2169
|
-
} else if (fields[i].startsWith("PS")) {
|
|
2170
|
-
allKnownFields = false;
|
|
2171
|
-
decodeResult.remaining.text += fields[i];
|
|
2172
2618
|
} else if (fields[i].startsWith("AF")) {
|
|
2173
|
-
|
|
2174
|
-
allKnownFields = allKnownFields && af;
|
|
2619
|
+
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2175
2620
|
} else if (fields[i].startsWith("TD")) {
|
|
2176
|
-
|
|
2177
|
-
allKnownFields = allKnownFields && td;
|
|
2621
|
+
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2178
2622
|
} else if (fields[i].startsWith("FX")) {
|
|
2179
2623
|
decodeResult.raw.free_text = fields[i].substring(2);
|
|
2180
2624
|
decodeResult.formatted.items.push({
|
|
@@ -2185,23 +2629,21 @@ var H1Helper = class {
|
|
|
2185
2629
|
});
|
|
2186
2630
|
} else {
|
|
2187
2631
|
decodeResult.remaining.text += "/" + fields[i];
|
|
2188
|
-
allKnownFields = false;
|
|
2189
2632
|
}
|
|
2190
2633
|
}
|
|
2191
2634
|
if (decodeResult.formatted.items.length > 0) {
|
|
2192
2635
|
ResultFormatter.checksum(decodeResult, checksum);
|
|
2193
2636
|
}
|
|
2194
|
-
return
|
|
2637
|
+
return true;
|
|
2195
2638
|
}
|
|
2196
2639
|
};
|
|
2197
2640
|
function processAirField(decodeResult, data) {
|
|
2198
2641
|
if (data.length === 2) {
|
|
2199
2642
|
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
2200
2643
|
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
2201
|
-
|
|
2644
|
+
} else {
|
|
2645
|
+
decodeResult.remaining.text += "AF/" + data.join(",");
|
|
2202
2646
|
}
|
|
2203
|
-
decodeResult.remaining.text += "AF/" + data.join(",");
|
|
2204
|
-
return false;
|
|
2205
2647
|
}
|
|
2206
2648
|
function processTimeOfDeparture(decodeResult, data) {
|
|
2207
2649
|
if (data.length === 2) {
|
|
@@ -2219,10 +2661,9 @@ function processTimeOfDeparture(decodeResult, data) {
|
|
|
2219
2661
|
label: "Estimated Departure Time",
|
|
2220
2662
|
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2221
2663
|
});
|
|
2222
|
-
|
|
2664
|
+
} else {
|
|
2665
|
+
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
2223
2666
|
}
|
|
2224
|
-
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
2225
|
-
return false;
|
|
2226
2667
|
}
|
|
2227
2668
|
function processIdentification(decodeResult, data) {
|
|
2228
2669
|
ResultFormatter.tail(decodeResult, data[0]);
|
|
@@ -2234,7 +2675,6 @@ function processIdentification(decodeResult, data) {
|
|
|
2234
2675
|
}
|
|
2235
2676
|
}
|
|
2236
2677
|
function processDT(decodeResult, data) {
|
|
2237
|
-
let allKnownFields = true;
|
|
2238
2678
|
if (!decodeResult.raw.arrival_icao) {
|
|
2239
2679
|
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2240
2680
|
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
@@ -2247,19 +2687,16 @@ function processDT(decodeResult, data) {
|
|
|
2247
2687
|
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2248
2688
|
}
|
|
2249
2689
|
if (data.length > 3) {
|
|
2250
|
-
ResultFormatter.eta(decodeResult, data[3]);
|
|
2690
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2251
2691
|
}
|
|
2252
2692
|
if (data.length > 4) {
|
|
2253
2693
|
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2254
2694
|
}
|
|
2255
2695
|
if (data.length > 5) {
|
|
2256
|
-
allKnownFields = false;
|
|
2257
2696
|
decodeResult.remaining.text += "," + data.slice(5).join(",");
|
|
2258
2697
|
}
|
|
2259
|
-
return allKnownFields;
|
|
2260
2698
|
}
|
|
2261
2699
|
function processLR(decodeResult, data) {
|
|
2262
|
-
let allKnownFields = true;
|
|
2263
2700
|
if (data.length === 19) {
|
|
2264
2701
|
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2265
2702
|
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
@@ -2267,34 +2704,47 @@ function processLR(decodeResult, data) {
|
|
|
2267
2704
|
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2268
2705
|
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2269
2706
|
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2270
|
-
allKnownFields = false;
|
|
2271
2707
|
} else {
|
|
2272
|
-
|
|
2708
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2273
2709
|
}
|
|
2274
|
-
return allKnownFields;
|
|
2275
2710
|
}
|
|
2276
2711
|
function parseMessageType(decodeResult, messageType) {
|
|
2277
|
-
let decoded = true;
|
|
2278
2712
|
const parts = messageType.split("#");
|
|
2279
2713
|
if (parts.length == 1) {
|
|
2280
|
-
|
|
2281
|
-
|
|
2714
|
+
const type = parts[0].substring(0, 3);
|
|
2715
|
+
if (type === "POS" && parts[0].length !== 3) {
|
|
2716
|
+
processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
2282
2717
|
}
|
|
2283
|
-
return
|
|
2718
|
+
return processMessageType(decodeResult, type);
|
|
2284
2719
|
} else if (parts.length == 2) {
|
|
2285
2720
|
if (parts[0].length > 0) {
|
|
2286
2721
|
decodeResult.remaining.text += parts[0].substring(0, 3);
|
|
2287
2722
|
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
2288
|
-
decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
|
|
2723
|
+
decodeResult.remaining.text += "#" + (parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3));
|
|
2289
2724
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2725
|
+
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
2726
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
2727
|
+
processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
2292
2728
|
}
|
|
2293
|
-
decodeResult
|
|
2294
|
-
|
|
2729
|
+
processMessageType(decodeResult, type);
|
|
2730
|
+
} else {
|
|
2731
|
+
decodeResult.remaining.text += messageType;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
function processMessageType(decodeResult, type) {
|
|
2735
|
+
if (type === "FPN") {
|
|
2736
|
+
decodeResult.formatted.description = "Flight Plan";
|
|
2737
|
+
} else if (type === "FTX") {
|
|
2738
|
+
decodeResult.formatted.description = "Free Text";
|
|
2739
|
+
} else if (type === "INI") {
|
|
2740
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2741
|
+
} else if (type === "POS") {
|
|
2742
|
+
decodeResult.formatted.description = "Position Report";
|
|
2743
|
+
} else if (type === "PRG") {
|
|
2744
|
+
decodeResult.formatted.description = "Progress Report";
|
|
2745
|
+
} else {
|
|
2746
|
+
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2295
2747
|
}
|
|
2296
|
-
decodeResult.remaining.text += messageType;
|
|
2297
|
-
return false;
|
|
2298
2748
|
}
|
|
2299
2749
|
function processDC(decodeResult, data) {
|
|
2300
2750
|
decodeResult.raw.message_date = data[0];
|
|
@@ -2303,13 +2753,9 @@ function processDC(decodeResult, data) {
|
|
|
2303
2753
|
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2304
2754
|
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2305
2755
|
decodeResult.raw.message_timestamp = time;
|
|
2306
|
-
} else {
|
|
2307
|
-
return false;
|
|
2308
2756
|
}
|
|
2309
|
-
return true;
|
|
2310
2757
|
}
|
|
2311
2758
|
function processPS(decodeResult, data) {
|
|
2312
|
-
let allKnownFields = true;
|
|
2313
2759
|
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2314
2760
|
if (position) {
|
|
2315
2761
|
decodeResult.raw.position = position;
|
|
@@ -2319,8 +2765,6 @@ function processPS(decodeResult, data) {
|
|
|
2319
2765
|
label: "Aircraft Position",
|
|
2320
2766
|
value: CoordinateUtils.coordinateString(position)
|
|
2321
2767
|
});
|
|
2322
|
-
} else {
|
|
2323
|
-
allKnownFields = false;
|
|
2324
2768
|
}
|
|
2325
2769
|
if (data.length === 9) {
|
|
2326
2770
|
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
@@ -2339,11 +2783,8 @@ function processPS(decodeResult, data) {
|
|
|
2339
2783
|
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2340
2784
|
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
2341
2785
|
}
|
|
2342
|
-
allKnownFields = false;
|
|
2343
|
-
return allKnownFields;
|
|
2344
2786
|
}
|
|
2345
2787
|
function processPosition2(decodeResult, data) {
|
|
2346
|
-
let allKnownFields = true;
|
|
2347
2788
|
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2348
2789
|
if (position) {
|
|
2349
2790
|
decodeResult.raw.position = position;
|
|
@@ -2353,8 +2794,6 @@ function processPosition2(decodeResult, data) {
|
|
|
2353
2794
|
label: "Aircraft Position",
|
|
2354
2795
|
value: CoordinateUtils.coordinateString(position)
|
|
2355
2796
|
});
|
|
2356
|
-
} else {
|
|
2357
|
-
allKnownFields = false;
|
|
2358
2797
|
}
|
|
2359
2798
|
if (data.length >= 10) {
|
|
2360
2799
|
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
@@ -2369,8 +2808,6 @@ function processPosition2(decodeResult, data) {
|
|
|
2369
2808
|
ResultFormatter.unknown(decodeResult, data[12]);
|
|
2370
2809
|
ResultFormatter.unknown(decodeResult, data[13]);
|
|
2371
2810
|
}
|
|
2372
|
-
allKnownFields = false;
|
|
2373
|
-
return allKnownFields;
|
|
2374
2811
|
}
|
|
2375
2812
|
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2376
2813
|
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
@@ -2393,175 +2830,23 @@ function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
|
2393
2830
|
});
|
|
2394
2831
|
}
|
|
2395
2832
|
|
|
2396
|
-
// lib/plugins/
|
|
2397
|
-
var
|
|
2398
|
-
name = "label-h1
|
|
2833
|
+
// lib/plugins/Label_H1.ts
|
|
2834
|
+
var Label_H1 = class extends DecoderPlugin {
|
|
2835
|
+
name = "label-h1";
|
|
2399
2836
|
qualifiers() {
|
|
2400
2837
|
return {
|
|
2401
|
-
labels: ["H1"]
|
|
2402
|
-
preambles: ["FPN", "#M1BFPN"]
|
|
2838
|
+
labels: ["H1"]
|
|
2403
2839
|
};
|
|
2404
2840
|
}
|
|
2405
2841
|
decode(message, options = {}) {
|
|
2406
2842
|
let decodeResult = this.defaultResult();
|
|
2407
2843
|
decodeResult.decoder.name = this.name;
|
|
2408
|
-
decodeResult.formatted.description = "Flight Plan";
|
|
2409
2844
|
decodeResult.message = message;
|
|
2410
2845
|
decodeResult.remaining.text = "";
|
|
2411
2846
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
2412
|
-
const
|
|
2413
|
-
decodeResult.decoded =
|
|
2414
|
-
decodeResult.decoder.decodeLevel =
|
|
2415
|
-
if (decodeResult.formatted.items.length === 0) {
|
|
2416
|
-
if (options.debug) {
|
|
2417
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2418
|
-
}
|
|
2419
|
-
decodeResult.remaining.text = message.text;
|
|
2420
|
-
decodeResult.decoded = false;
|
|
2421
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2422
|
-
}
|
|
2423
|
-
return decodeResult;
|
|
2424
|
-
}
|
|
2425
|
-
};
|
|
2426
|
-
|
|
2427
|
-
// lib/plugins/Label_H1_FTX.ts
|
|
2428
|
-
var Label_H1_FTX = class extends DecoderPlugin {
|
|
2429
|
-
name = "label-h1-ftx";
|
|
2430
|
-
qualifiers() {
|
|
2431
|
-
return {
|
|
2432
|
-
labels: ["H1"],
|
|
2433
|
-
preambles: ["FTX", "- #MDFTX"]
|
|
2434
|
-
};
|
|
2435
|
-
}
|
|
2436
|
-
decode(message, options = {}) {
|
|
2437
|
-
let decodeResult = this.defaultResult();
|
|
2438
|
-
decodeResult.decoder.name = this.name;
|
|
2439
|
-
decodeResult.formatted.description = "Free Text";
|
|
2440
|
-
decodeResult.message = message;
|
|
2441
|
-
decodeResult.remaining.text = "";
|
|
2442
|
-
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2443
|
-
decodeResult.decoded = true;
|
|
2444
|
-
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2445
|
-
if (decodeResult.formatted.items.length === 0) {
|
|
2446
|
-
if (options.debug) {
|
|
2447
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2448
|
-
}
|
|
2449
|
-
decodeResult.remaining.text = message.text;
|
|
2450
|
-
decodeResult.decoded = false;
|
|
2451
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2452
|
-
}
|
|
2453
|
-
return decodeResult;
|
|
2454
|
-
}
|
|
2455
|
-
};
|
|
2456
|
-
|
|
2457
|
-
// lib/plugins/Label_H1_INI.ts
|
|
2458
|
-
var Label_H1_INI = class extends DecoderPlugin {
|
|
2459
|
-
// eslint-disable-line camelcase
|
|
2460
|
-
name = "label-h1-ini";
|
|
2461
|
-
qualifiers() {
|
|
2462
|
-
return {
|
|
2463
|
-
labels: ["H1"],
|
|
2464
|
-
preambles: ["INI", "- #MDINI"]
|
|
2465
|
-
};
|
|
2466
|
-
}
|
|
2467
|
-
decode(message, options = {}) {
|
|
2468
|
-
const decodeResult = this.defaultResult();
|
|
2469
|
-
decodeResult.decoder.name = this.name;
|
|
2470
|
-
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2471
|
-
decodeResult.message = message;
|
|
2472
|
-
decodeResult.remaining.text = "";
|
|
2473
|
-
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2474
|
-
decodeResult.decoded = true;
|
|
2475
|
-
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2476
|
-
if (decodeResult.formatted.items.length === 0) {
|
|
2477
|
-
if (options.debug) {
|
|
2478
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2479
|
-
}
|
|
2480
|
-
decodeResult.remaining.text = message.text;
|
|
2481
|
-
decodeResult.decoded = false;
|
|
2482
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2483
|
-
}
|
|
2484
|
-
return decodeResult;
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
|
|
2488
|
-
// lib/plugins/Label_H1_OHMA.ts
|
|
2489
|
-
var zlib = __toESM(require("minizlib"));
|
|
2490
|
-
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
2491
|
-
name = "label-h1-ohma";
|
|
2492
|
-
qualifiers() {
|
|
2493
|
-
return {
|
|
2494
|
-
labels: ["H1"],
|
|
2495
|
-
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
2496
|
-
};
|
|
2497
|
-
}
|
|
2498
|
-
decode(message, options = {}) {
|
|
2499
|
-
let decodeResult = this.defaultResult();
|
|
2500
|
-
decodeResult.decoder.name = this.name;
|
|
2501
|
-
decodeResult.formatted.description = "OHMA Message";
|
|
2502
|
-
decodeResult.message = message;
|
|
2503
|
-
decodeResult.remaining.text = "";
|
|
2504
|
-
const data = message.text.split("OHMA")[1];
|
|
2505
|
-
try {
|
|
2506
|
-
const compressedBuffer = Buffer.from(data, "base64");
|
|
2507
|
-
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
2508
|
-
decompress.write(compressedBuffer);
|
|
2509
|
-
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
2510
|
-
const result = decompress.read();
|
|
2511
|
-
const jsonText = result.toString();
|
|
2512
|
-
let formattedMsg;
|
|
2513
|
-
let jsonMessage;
|
|
2514
|
-
try {
|
|
2515
|
-
jsonMessage = JSON.parse(jsonText).message;
|
|
2516
|
-
} catch {
|
|
2517
|
-
jsonMessage = jsonText;
|
|
2518
|
-
}
|
|
2519
|
-
try {
|
|
2520
|
-
const ohmaMsg = JSON.parse(jsonMessage);
|
|
2521
|
-
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
2522
|
-
} catch {
|
|
2523
|
-
formattedMsg = jsonMessage;
|
|
2524
|
-
}
|
|
2525
|
-
decodeResult.decoded = true;
|
|
2526
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2527
|
-
decodeResult.raw.ohma = jsonText;
|
|
2528
|
-
decodeResult.formatted.items.push({
|
|
2529
|
-
type: "ohma",
|
|
2530
|
-
code: "OHMA",
|
|
2531
|
-
label: "OHMA Downlink",
|
|
2532
|
-
value: formattedMsg
|
|
2533
|
-
});
|
|
2534
|
-
} catch (e) {
|
|
2535
|
-
if (options.debug) {
|
|
2536
|
-
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
2537
|
-
}
|
|
2538
|
-
decodeResult.remaining.text += message.text;
|
|
2539
|
-
decodeResult.decoded = false;
|
|
2540
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2541
|
-
}
|
|
2542
|
-
return decodeResult;
|
|
2543
|
-
}
|
|
2544
|
-
};
|
|
2545
|
-
|
|
2546
|
-
// lib/plugins/Label_H1_POS.ts
|
|
2547
|
-
var Label_H1_POS = class extends DecoderPlugin {
|
|
2548
|
-
name = "label-h1-pos";
|
|
2549
|
-
qualifiers() {
|
|
2550
|
-
return {
|
|
2551
|
-
labels: ["H1", "4J"],
|
|
2552
|
-
preambles: ["POS", "#M1BPOS", "/.POS"]
|
|
2553
|
-
//TODO - support data before #
|
|
2554
|
-
};
|
|
2555
|
-
}
|
|
2556
|
-
decode(message, options = {}) {
|
|
2557
|
-
let decodeResult = this.defaultResult();
|
|
2558
|
-
decodeResult.decoder.name = this.name;
|
|
2559
|
-
decodeResult.formatted.description = "Position Report";
|
|
2560
|
-
decodeResult.message = message;
|
|
2561
|
-
decodeResult.remaining.text = "";
|
|
2562
|
-
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2563
|
-
decodeResult.decoded = true;
|
|
2564
|
-
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2847
|
+
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2848
|
+
decodeResult.decoded = decoded;
|
|
2849
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text.length === 0 ? "full" : "partial";
|
|
2565
2850
|
if (decodeResult.formatted.items.length === 0) {
|
|
2566
2851
|
if (options.debug) {
|
|
2567
2852
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
@@ -2574,62 +2859,6 @@ var Label_H1_POS = class extends DecoderPlugin {
|
|
|
2574
2859
|
}
|
|
2575
2860
|
};
|
|
2576
2861
|
|
|
2577
|
-
// lib/plugins/Label_H1_WRN.ts
|
|
2578
|
-
var Label_H1_WRN = class extends DecoderPlugin {
|
|
2579
|
-
name = "label-h1-wrn";
|
|
2580
|
-
qualifiers() {
|
|
2581
|
-
return {
|
|
2582
|
-
labels: ["H1"],
|
|
2583
|
-
preambles: ["WRN", "#CFBWRN"]
|
|
2584
|
-
};
|
|
2585
|
-
}
|
|
2586
|
-
decode(message, options = {}) {
|
|
2587
|
-
let decodeResult = this.defaultResult();
|
|
2588
|
-
decodeResult.decoder.name = this.name;
|
|
2589
|
-
decodeResult.formatted.description = "Warning Message";
|
|
2590
|
-
decodeResult.message = message;
|
|
2591
|
-
const parts = message.text.split("/WN");
|
|
2592
|
-
if (parts.length > 1) {
|
|
2593
|
-
decodeResult.remaining.text = "";
|
|
2594
|
-
const fields = parts[0].split("/");
|
|
2595
|
-
for (let i = 1; i < fields.length; i++) {
|
|
2596
|
-
const field = fields[i];
|
|
2597
|
-
if (field.startsWith("PN")) {
|
|
2598
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2599
|
-
} else {
|
|
2600
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2601
|
-
}
|
|
2602
|
-
}
|
|
2603
|
-
const data = parts[1].substring(0, 20);
|
|
2604
|
-
const msg = parts[1].substring(20);
|
|
2605
|
-
const datetime = data.substring(0, 12);
|
|
2606
|
-
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2607
|
-
processUnknown2(decodeResult, data.substring(12));
|
|
2608
|
-
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2609
|
-
decodeResult.raw.warning_message = msg;
|
|
2610
|
-
decodeResult.formatted.items.push({
|
|
2611
|
-
type: "warning",
|
|
2612
|
-
code: "WRN",
|
|
2613
|
-
label: "Warning Message",
|
|
2614
|
-
value: decodeResult.raw.warning_message
|
|
2615
|
-
});
|
|
2616
|
-
decodeResult.decoded = true;
|
|
2617
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2618
|
-
} else {
|
|
2619
|
-
if (options.debug) {
|
|
2620
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2621
|
-
}
|
|
2622
|
-
decodeResult.remaining.text = message.text;
|
|
2623
|
-
decodeResult.decoded = false;
|
|
2624
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2625
|
-
}
|
|
2626
|
-
return decodeResult;
|
|
2627
|
-
}
|
|
2628
|
-
};
|
|
2629
|
-
function processUnknown2(decodeResult, value) {
|
|
2630
|
-
decodeResult.remaining.text += value;
|
|
2631
|
-
}
|
|
2632
|
-
|
|
2633
2862
|
// lib/plugins/Label_HX.ts
|
|
2634
2863
|
var Label_HX = class extends DecoderPlugin {
|
|
2635
2864
|
name = "label-hx";
|
|
@@ -2673,7 +2902,7 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
2673
2902
|
});
|
|
2674
2903
|
}
|
|
2675
2904
|
if (decodeResult.decoded) {
|
|
2676
|
-
if (decodeResult.remaining.text
|
|
2905
|
+
if (!decodeResult.remaining.text)
|
|
2677
2906
|
decodeResult.decoder.decodeLevel = "full";
|
|
2678
2907
|
else
|
|
2679
2908
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -2828,7 +3057,7 @@ var Label_QR = class extends DecoderPlugin {
|
|
|
2828
3057
|
}
|
|
2829
3058
|
];
|
|
2830
3059
|
decodeResult.decoded = true;
|
|
2831
|
-
if (decodeResult.remaining.text
|
|
3060
|
+
if (!decodeResult.remaining.text)
|
|
2832
3061
|
decodeResult.decoder.decodeLevel = "full";
|
|
2833
3062
|
else
|
|
2834
3063
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -2873,7 +3102,7 @@ var Label_QP = class extends DecoderPlugin {
|
|
|
2873
3102
|
}
|
|
2874
3103
|
];
|
|
2875
3104
|
decodeResult.decoded = true;
|
|
2876
|
-
if (decodeResult.remaining.text
|
|
3105
|
+
if (!decodeResult.remaining.text)
|
|
2877
3106
|
decodeResult.decoder.decodeLevel = "full";
|
|
2878
3107
|
else
|
|
2879
3108
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -2918,7 +3147,7 @@ var Label_QS = class extends DecoderPlugin {
|
|
|
2918
3147
|
}
|
|
2919
3148
|
];
|
|
2920
3149
|
decodeResult.decoded = true;
|
|
2921
|
-
if (decodeResult.remaining.text
|
|
3150
|
+
if (!decodeResult.remaining.text)
|
|
2922
3151
|
decodeResult.decoder.decodeLevel = "full";
|
|
2923
3152
|
else
|
|
2924
3153
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -2980,7 +3209,7 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
2980
3209
|
});
|
|
2981
3210
|
}
|
|
2982
3211
|
decodeResult.decoded = true;
|
|
2983
|
-
if (decodeResult.remaining.text
|
|
3212
|
+
if (!decodeResult.remaining.text)
|
|
2984
3213
|
decodeResult.decoder.decodeLevel = "full";
|
|
2985
3214
|
else
|
|
2986
3215
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -3800,7 +4029,7 @@ var MessageDecoder = class {
|
|
|
3800
4029
|
this.plugins = [];
|
|
3801
4030
|
this.debug = false;
|
|
3802
4031
|
this.registerPlugin(new Label_ColonComma(this));
|
|
3803
|
-
this.registerPlugin(new
|
|
4032
|
+
this.registerPlugin(new Label_5Z_Slash(this));
|
|
3804
4033
|
this.registerPlugin(new Label_10_LDR(this));
|
|
3805
4034
|
this.registerPlugin(new Label_10_POS(this));
|
|
3806
4035
|
this.registerPlugin(new Label_10_Slash(this));
|
|
@@ -3811,21 +4040,24 @@ var MessageDecoder = class {
|
|
|
3811
4040
|
this.registerPlugin(new Label_16_N_Space(this));
|
|
3812
4041
|
this.registerPlugin(new Label_20_POS(this));
|
|
3813
4042
|
this.registerPlugin(new Label_21_POS(this));
|
|
4043
|
+
this.registerPlugin(new Label_24_Slash(this));
|
|
3814
4044
|
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
3815
4045
|
this.registerPlugin(new Label_44_ETA(this));
|
|
3816
4046
|
this.registerPlugin(new Label_44_IN(this));
|
|
3817
4047
|
this.registerPlugin(new Label_44_OFF(this));
|
|
3818
4048
|
this.registerPlugin(new Label_44_ON(this));
|
|
3819
4049
|
this.registerPlugin(new Label_44_POS(this));
|
|
4050
|
+
this.registerPlugin(new Label_4A(this));
|
|
4051
|
+
this.registerPlugin(new Label_4A_01(this));
|
|
4052
|
+
this.registerPlugin(new Label_4A_DIS(this));
|
|
4053
|
+
this.registerPlugin(new Label_4A_DOOR(this));
|
|
4054
|
+
this.registerPlugin(new Label_4A_Slash_01(this));
|
|
3820
4055
|
this.registerPlugin(new Label_4N(this));
|
|
3821
4056
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
3822
|
-
this.registerPlugin(new Label_H1_FPN(this));
|
|
3823
4057
|
this.registerPlugin(new Label_H1_FLR(this));
|
|
3824
|
-
this.registerPlugin(new Label_H1_FTX(this));
|
|
3825
|
-
this.registerPlugin(new Label_H1_INI(this));
|
|
3826
4058
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
3827
|
-
this.registerPlugin(new Label_H1_POS(this));
|
|
3828
4059
|
this.registerPlugin(new Label_H1_WRN(this));
|
|
4060
|
+
this.registerPlugin(new Label_H1(this));
|
|
3829
4061
|
this.registerPlugin(new Label_HX(this));
|
|
3830
4062
|
this.registerPlugin(new Label_80(this));
|
|
3831
4063
|
this.registerPlugin(new Label_83(this));
|
|
@@ -3873,29 +4105,30 @@ var MessageDecoder = class {
|
|
|
3873
4105
|
console.log("Usable plugins");
|
|
3874
4106
|
console.log(usablePlugins);
|
|
3875
4107
|
}
|
|
3876
|
-
let result
|
|
3877
|
-
|
|
3878
|
-
|
|
4108
|
+
let result = {
|
|
4109
|
+
decoded: false,
|
|
4110
|
+
error: "No known decoder plugin for this message",
|
|
4111
|
+
decoder: {
|
|
4112
|
+
name: "none",
|
|
4113
|
+
type: "none",
|
|
4114
|
+
decodeLevel: "none"
|
|
4115
|
+
},
|
|
4116
|
+
message,
|
|
4117
|
+
remaining: {
|
|
4118
|
+
text: message.text
|
|
4119
|
+
},
|
|
4120
|
+
raw: {},
|
|
4121
|
+
formatted: {
|
|
4122
|
+
description: "Not Decoded",
|
|
4123
|
+
items: []
|
|
4124
|
+
}
|
|
4125
|
+
};
|
|
4126
|
+
for (let i = 0; i < usablePlugins.length; i++) {
|
|
4127
|
+
const plugin = usablePlugins[i];
|
|
3879
4128
|
result = plugin.decode(message);
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
error: "No known decoder plugin for this message",
|
|
3884
|
-
decoder: {
|
|
3885
|
-
name: "none",
|
|
3886
|
-
type: "none",
|
|
3887
|
-
decodeLevel: "none"
|
|
3888
|
-
},
|
|
3889
|
-
message,
|
|
3890
|
-
remaining: {
|
|
3891
|
-
text: message.text
|
|
3892
|
-
},
|
|
3893
|
-
raw: {},
|
|
3894
|
-
formatted: {
|
|
3895
|
-
description: "Not Decoded",
|
|
3896
|
-
items: []
|
|
3897
|
-
}
|
|
3898
|
-
};
|
|
4129
|
+
if (result.decoded) {
|
|
4130
|
+
break;
|
|
4131
|
+
}
|
|
3899
4132
|
}
|
|
3900
4133
|
if (options.debug) {
|
|
3901
4134
|
console.log("Result");
|