@airframes/acars-decoder 1.6.0 → 1.6.1

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 ADDED
@@ -0,0 +1,2870 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // index.ts
31
+ var acars_decoder_typescript_exports = {};
32
+ __export(acars_decoder_typescript_exports, {
33
+ IcaoDecoder: () => IcaoDecoder,
34
+ MessageDecoder: () => MessageDecoder
35
+ });
36
+ module.exports = __toCommonJS(acars_decoder_typescript_exports);
37
+
38
+ // lib/IcaoDecoder.ts
39
+ var IcaoDecoder = class {
40
+ name;
41
+ icao;
42
+ constructor(icao) {
43
+ this.name = "icao-decoder-typescript";
44
+ this.icao = icao;
45
+ }
46
+ isMilitary() {
47
+ let i = this.icao;
48
+ return i.match(/^adf[7-9]/) || i.match(/^adf[a-f]/) || i.match(/^a(e|f)/) || i.match(/^0100(7|8)/) || i.match(/^0a4/) || i.match(/^33ff/) || i >= "350000" && i <= "37ffff" || i.match(/^3a(8|9|[a-f])/) || i.match(/^3b/) || i.match(/^3e(a|b)/) || i.match(/^3f([4-9]|[a-b])/) || i.match(/^4000[0-3]/) || i.match(/^43c/) || i.match(/^44[4-7]/) && i != "447ac7" || i.match(/^44f/) || i.match(/^457/) || i.match(/^45f4/) || i.match(/^468[0-3]/) || i.match(/^473c0/) || i.match(/^4781/) || i.match(/^480/) || i.match(/^48d8[0-7]/) || i.match(/^497c/) || i.match(/^49842/) || i.match(/^4b7/) || i.match(/^4b82/) || i.match(/^506f/) || i.match(/^70c07/) || i.match(/^7102[5-8]/) || i.match(/^7103[8-9]/) || i.match(/^738a/) || i.match(/^7c8([2-4]|8)/) || i >= "7c9000" && i <= "7cbfff" || i.match(/^7[d-f]/) || i.match(/^8002/) || i.match(/^c[2-3]/) || i.match(/^e4[0-1]/) || i.match(/^e806/);
49
+ }
50
+ };
51
+
52
+ // lib/DecoderPlugin.ts
53
+ var DecoderPlugin = class {
54
+ decoder;
55
+ name = "unknown";
56
+ defaultResult = {
57
+ decoded: false,
58
+ decoder: {
59
+ name: "unknown",
60
+ type: "pattern-match",
61
+ decodeLevel: "none"
62
+ },
63
+ formatted: {
64
+ description: "Unknown",
65
+ items: []
66
+ },
67
+ raw: {},
68
+ remaining: {}
69
+ };
70
+ options;
71
+ constructor(decoder, options = {}) {
72
+ this.decoder = decoder;
73
+ this.options = options;
74
+ }
75
+ id() {
76
+ console.log("DecoderPlugin subclass has not overriden id() to provide a unique ID for this plugin!");
77
+ return "abstract_decoder_plugin";
78
+ }
79
+ meetsStateRequirements() {
80
+ return true;
81
+ }
82
+ // onRegister(store: Store<any>) {
83
+ // this.store = store;
84
+ // }
85
+ qualifiers() {
86
+ const labels = [];
87
+ return {
88
+ labels
89
+ };
90
+ }
91
+ decode(message) {
92
+ const decodeResult = this.defaultResult;
93
+ decodeResult.remaining.text = message.text;
94
+ return decodeResult;
95
+ }
96
+ };
97
+
98
+ // lib/plugins/Label_5Z.ts
99
+ var Label_5Z = class extends DecoderPlugin {
100
+ name = "label-5z";
101
+ descriptions = {
102
+ B1: "Request Weight and Balance",
103
+ B3: "Request Departure Clearance",
104
+ CD: "Weight and Balance",
105
+ CG: "Request Pre-departure clearance, PDC",
106
+ CM: "Crew Scheduling",
107
+ C3: "Off Message",
108
+ C4: "Flight Dispatch",
109
+ C5: "Maintenance Message",
110
+ C6: "Customer Service",
111
+ 10: "PIREP",
112
+ C11: "International PIREP",
113
+ DS: "Late Message",
114
+ D3: "Holding Pattern Message",
115
+ D6: "From-To + Date",
116
+ D7: "From-To + Alternate + Time",
117
+ EO: "In Range",
118
+ PW: "Position Weather",
119
+ RL: "Request Release",
120
+ R3: "Request HOWGOZIT Message",
121
+ R4: "Request the Latest POSBD",
122
+ TC: "From-To Fuel",
123
+ WB: "From-To",
124
+ W1: "Request Weather for City"
125
+ };
126
+ qualifiers() {
127
+ return {
128
+ labels: ["5Z"]
129
+ };
130
+ }
131
+ decode(message, options = {}) {
132
+ const decodeResult = this.defaultResult;
133
+ decodeResult.decoder.name = this.name;
134
+ decodeResult.formatted.description = "Airline Designated Downlink";
135
+ const uaRegex = /^\/(?<type>\w+) (?<remainder>.+)/;
136
+ let results = message.text.match(uaRegex);
137
+ if (results && results.length >= 2) {
138
+ const type = results.groups.type.split("/")[0];
139
+ const { remainder } = results.groups;
140
+ const typeDescription = this.descriptions[type] ? this.descriptions[type] : "Unknown";
141
+ decodeResult.raw.airline = "United Airlines";
142
+ decodeResult.formatted.items.push({
143
+ type: "airline",
144
+ label: "Airline",
145
+ value: "United Airlines"
146
+ });
147
+ decodeResult.raw.message_type = type;
148
+ decodeResult.formatted.items.push({
149
+ type: "message_type",
150
+ label: "Message Type",
151
+ value: `${typeDescription} (${type})`
152
+ });
153
+ if (type === "B3") {
154
+ const rdcRegex = /^(?<from>\w\w\w)(?<to>\w\w\w) (?<unknown1>\d\d) R(?<runway>.+) G(?<unknown2>.+)$/;
155
+ results = remainder.match(rdcRegex);
156
+ if (results) {
157
+ decodeResult.raw.origin = results.groups.from;
158
+ decodeResult.formatted.items.push({
159
+ type: "origin",
160
+ label: "Origin",
161
+ value: `${results.groups.from}`
162
+ });
163
+ decodeResult.raw.destination = results.groups.to;
164
+ decodeResult.formatted.items.push({
165
+ type: "destination",
166
+ label: "Destination",
167
+ value: `${results.groups.to}`
168
+ });
169
+ decodeResult.formatted.items.push({
170
+ type: "unknown1",
171
+ label: "Unknown Field 1",
172
+ value: `${results.groups.unknown1}`
173
+ });
174
+ decodeResult.raw.runway = results.groups.runway;
175
+ decodeResult.formatted.items.push({
176
+ type: "runway",
177
+ label: "Runway",
178
+ value: `${results.groups.runway}`
179
+ });
180
+ decodeResult.formatted.items.push({
181
+ type: "unknown2",
182
+ label: "Unknown Field 2",
183
+ value: `${results.groups.unknown2}`
184
+ });
185
+ } else {
186
+ if (options.debug) {
187
+ console.log(`Decoder: Unkown 5Z RDC format: ${remainder}`);
188
+ }
189
+ }
190
+ } else {
191
+ decodeResult.remaining.text = remainder;
192
+ }
193
+ decodeResult.decoded = true;
194
+ decodeResult.decoder.decodeLevel = "partial";
195
+ } else {
196
+ if (options.debug) {
197
+ console.log(`Decoder: Unknown 5Z message: ${message.text}`);
198
+ }
199
+ decodeResult.remaining.text = message.text;
200
+ decodeResult.decoded = false;
201
+ decodeResult.decoder.decodeLevel = "none";
202
+ }
203
+ return decodeResult;
204
+ }
205
+ };
206
+
207
+ // lib/plugins/Label_12_N_Space.ts
208
+ var Label_12_N_Space = class extends DecoderPlugin {
209
+ name = "label-12-n-space";
210
+ qualifiers() {
211
+ return {
212
+ labels: ["12"],
213
+ preambles: ["N "]
214
+ };
215
+ }
216
+ decode(message, options = {}) {
217
+ const decodeResult = this.defaultResult;
218
+ decodeResult.decoder.name = this.name;
219
+ decodeResult.formatted.description = "Position Report";
220
+ decodeResult.message = message;
221
+ const variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*),.(?<airframe>.*),(?<unkwn3>.*)$/;
222
+ let results;
223
+ if (results = message.text.match(variant1Regex)) {
224
+ if (options.debug) {
225
+ console.log(`Label 12 N : results`);
226
+ console.log(results);
227
+ }
228
+ decodeResult.raw.latitude_direction = results.groups.lat;
229
+ decodeResult.raw.latitude = Number(results.groups.lat_coord);
230
+ decodeResult.raw.longitude_direction = results.groups.long;
231
+ decodeResult.raw.longitude = Number(results.groups.long_coord);
232
+ decodeResult.raw.flight_level = results.groups.alt == "GRD" || results.groups.alt == "***" ? "0" : Number(results.groups.alt);
233
+ decodeResult.formatted.items.push({
234
+ type: "aircraft_position",
235
+ code: "POS",
236
+ label: "Aircraft Position",
237
+ value: `${results.groups.lat_coord} ${decodeResult.raw.latitude_direction}, ${results.groups.long_coord} ${decodeResult.raw.longitude_direction}`
238
+ });
239
+ decodeResult.formatted.items.push({
240
+ type: "flight_level",
241
+ code: "FL",
242
+ label: "Flight Level",
243
+ value: decodeResult.raw.flight_level
244
+ });
245
+ decodeResult.remaining.text = `,${results.groups.unkwn1} ,${results.groups.unkwn2}, ${results.groups.unkwn3}`;
246
+ decodeResult.decoded = true;
247
+ decodeResult.decoder.decodeLevel = "partial";
248
+ } else {
249
+ if (options.debug) {
250
+ console.log(`Decoder: Unknown 12 message: ${message.text}`);
251
+ }
252
+ decodeResult.remaining.text = message.text;
253
+ decodeResult.decoded = false;
254
+ decodeResult.decoder.decodeLevel = "none";
255
+ }
256
+ return decodeResult;
257
+ }
258
+ };
259
+
260
+ // lib/utils/coordinate_utils.ts
261
+ var CoordinateUtils = class {
262
+ static decodeStringCoordinates(stringCoords) {
263
+ var results = {};
264
+ const firstChar = stringCoords.substring(0, 1);
265
+ let middleChar = stringCoords.substring(6, 7);
266
+ let longitudeChars = stringCoords.substring(7, 13);
267
+ if (middleChar == " ") {
268
+ middleChar = stringCoords.substring(7, 8);
269
+ longitudeChars = stringCoords.substring(8, 14);
270
+ }
271
+ if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
272
+ results.latitudeDirection = firstChar;
273
+ results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar === "S" ? -1 : 1);
274
+ results.longitudeDirection = middleChar;
275
+ results.longitude = Number(longitudeChars) / 1e3 * (middleChar === "W" ? -1 : 1);
276
+ } else {
277
+ return;
278
+ }
279
+ return results;
280
+ }
281
+ static coordinateString(coords) {
282
+ return `${Math.abs(coords.latitude)} ${coords.latitudeDirection}, ${Math.abs(coords.longitude)} ${coords.longitudeDirection}`;
283
+ }
284
+ static latLonToCoordinateString(lat, lon) {
285
+ const latDir = lat > 0 ? "N" : "S";
286
+ const lonDir = lon > 0 ? "E" : "W";
287
+ return `${Math.abs(lat)} ${latDir}, ${Math.abs(lon)} ${lonDir}`;
288
+ }
289
+ };
290
+
291
+ // lib/plugins/Label_15.ts
292
+ var Label_15 = class extends DecoderPlugin {
293
+ name = "label-5z";
294
+ qualifiers() {
295
+ return {
296
+ labels: ["15"],
297
+ preambles: ["(2"]
298
+ };
299
+ }
300
+ decode(message, options = {}) {
301
+ const decodeResult = this.defaultResult;
302
+ decodeResult.decoder.name = this.name;
303
+ decodeResult.formatted.description = "Position Report";
304
+ const twoZeeRegex = /^\(2(?<between>.+)\(Z$/;
305
+ const results = message.text.match(twoZeeRegex);
306
+ if (results) {
307
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.between.substr(0, 13));
308
+ if (decodeResult.raw.position) {
309
+ decodeResult.formatted.items.push({
310
+ type: "position",
311
+ code: "POS",
312
+ label: "Position",
313
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
314
+ });
315
+ }
316
+ }
317
+ decodeResult.decoded = true;
318
+ decodeResult.decoder.decodeLevel = "partial";
319
+ return decodeResult;
320
+ }
321
+ };
322
+
323
+ // lib/plugins/Label_15_FST.ts
324
+ var Label_15_FST = class extends DecoderPlugin {
325
+ name = "label-15-fst";
326
+ qualifiers() {
327
+ return {
328
+ labels: ["15"],
329
+ preambles: ["FST01"]
330
+ };
331
+ }
332
+ decode(message, options = {}) {
333
+ const decodeResult = this.defaultResult;
334
+ decodeResult.decoder.name = this.name;
335
+ decodeResult.formatted.description = "Position Report";
336
+ decodeResult.message = message;
337
+ decodeResult.raw.departure_icao = message.text.substring(5, 9);
338
+ decodeResult.raw.arrival_icao = message.text.substring(9, 13);
339
+ const stringCoords = message.text.substring(13);
340
+ const firstChar = stringCoords.substring(0, 1);
341
+ const middleChar = stringCoords.substring(7, 8);
342
+ decodeResult.raw.position = {};
343
+ if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
344
+ decodeResult.raw.position.latitudeDirection = firstChar;
345
+ decodeResult.raw.position.latitude = Number(stringCoords.substring(1, 7)) / 1e4 * (firstChar === "S" ? -1 : 1);
346
+ decodeResult.raw.position.longitudeDirection = middleChar;
347
+ decodeResult.raw.position.longitude = Number(stringCoords.substring(8, 26)) / 1e5 * (middleChar === "W" ? -1 : 1);
348
+ } else {
349
+ decodeResult.decoded = false;
350
+ decodeResult.decoder.decodeLevel = "none";
351
+ return decodeResult;
352
+ }
353
+ decodeResult.formatted.items.push({
354
+ type: "position",
355
+ label: "Position",
356
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
357
+ });
358
+ decodeResult.formatted.items.push({
359
+ type: "origin",
360
+ code: "ORG",
361
+ label: "Origin",
362
+ value: decodeResult.raw.departure_icao
363
+ });
364
+ decodeResult.formatted.items.push({
365
+ type: "destination",
366
+ code: "DST",
367
+ label: "Destination",
368
+ value: decodeResult.raw.arrival_icao
369
+ });
370
+ decodeResult.decoded = true;
371
+ decodeResult.decoder.decodeLevel = "full";
372
+ return decodeResult;
373
+ }
374
+ };
375
+
376
+ // lib/plugins/Label_16_N_Space.ts
377
+ var Label_16_N_Space = class extends DecoderPlugin {
378
+ name = "label-16-n-space";
379
+ qualifiers() {
380
+ return {
381
+ labels: ["16"],
382
+ preambles: ["N "]
383
+ };
384
+ }
385
+ decode(message, options = {}) {
386
+ const decodeResult = this.defaultResult;
387
+ decodeResult.decoder.name = this.name;
388
+ decodeResult.formatted.description = "Position Report";
389
+ decodeResult.message = message;
390
+ let variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*)$/;
391
+ let variant2Regex = /^(?<lat>[NS])\s(?<lat_coord>.*)\/(?<long>[EW])\s*(?<long_coord>.*)$/;
392
+ let results;
393
+ if (results = message.text.match(variant1Regex)) {
394
+ if (options.debug) {
395
+ console.log(`Label 16 N : results`);
396
+ console.log(results);
397
+ }
398
+ decodeResult.raw.latitude_direction = results.groups.lat;
399
+ decodeResult.raw.latitude = Number(results.groups.lat_coord);
400
+ decodeResult.raw.longitude_direction = results.groups.long;
401
+ decodeResult.raw.longitude = Number(results.groups.long_coord);
402
+ decodeResult.raw.flight_level = results.groups.alt == "GRD" || results.groups.alt == "***" ? "0" : Number(results.groups.alt);
403
+ decodeResult.formatted.items.push({
404
+ type: "aircraft_position",
405
+ code: "POS",
406
+ label: "Aircraft Position",
407
+ value: `${decodeResult.raw.latitude} ${decodeResult.raw.latitude_direction}, ${decodeResult.raw.longitude} ${decodeResult.raw.longitude_direction}`
408
+ });
409
+ decodeResult.formatted.items.push({
410
+ type: "flight_level",
411
+ code: "FL",
412
+ label: "Flight Level",
413
+ value: decodeResult.raw.flight_level
414
+ });
415
+ decodeResult.remaining.text = `,${results.groups.unkwn1} ,${results.groups.unkwn2}`;
416
+ decodeResult.decoded = true;
417
+ decodeResult.decoder.decodeLevel = "partial";
418
+ } else if (results = message.text.match(variant2Regex)) {
419
+ if (options.debug) {
420
+ console.log(`Label 16 N : results`);
421
+ console.log(results);
422
+ }
423
+ decodeResult.raw.latitude_direction = results.groups.lat;
424
+ decodeResult.raw.latitude = Number(results.groups.lat_coord);
425
+ decodeResult.raw.longitude_direction = results.groups.long;
426
+ decodeResult.raw.longitude = Number(results.groups.long_coord);
427
+ decodeResult.formatted.items.push({
428
+ type: "aircraft_position",
429
+ code: "POS",
430
+ label: "Aircraft Position",
431
+ value: `${results.groups.lat_coord} ${decodeResult.raw.latitude_direction}, ${results.groups.long_coord} ${decodeResult.raw.longitude_direction}`
432
+ });
433
+ decodeResult.decoded = true;
434
+ decodeResult.decoder.decodeLevel = "full";
435
+ } else {
436
+ if (options.debug) {
437
+ console.log(`Decoder: Unknown 16 message: ${message.text}`);
438
+ }
439
+ decodeResult.remaining.text = message.text;
440
+ decodeResult.decoded = false;
441
+ decodeResult.decoder.decodeLevel = "none";
442
+ }
443
+ return decodeResult;
444
+ }
445
+ };
446
+
447
+ // lib/DateTimeUtils.ts
448
+ var DateTimeUtils = class {
449
+ // Expects a four digit UTC time string (HHMM)
450
+ static UTCToString(UTCString) {
451
+ let utcDate = /* @__PURE__ */ new Date();
452
+ utcDate.setUTCHours(+UTCString.substr(0, 2), +UTCString.substr(2, 2), 0);
453
+ return utcDate.toTimeString();
454
+ }
455
+ // Expects a six digit date string and a four digit UTC time string
456
+ // (DDMMYY) (HHMM)
457
+ static UTCDateTimeToString(dateString, timeString) {
458
+ let utcDate = /* @__PURE__ */ new Date();
459
+ utcDate.setUTCDate(+dateString.substr(0, 2));
460
+ utcDate.setUTCMonth(+dateString.substr(2, 2));
461
+ if (dateString.length === 6) {
462
+ utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
463
+ }
464
+ if (timeString.length === 6) {
465
+ utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), +timeString.substr(4, 2));
466
+ } else {
467
+ utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), 0);
468
+ }
469
+ return utcDate.toUTCString();
470
+ }
471
+ /**
472
+ *
473
+ * @param time HHMMSS
474
+ * @returns seconds since midnight
475
+ */
476
+ static convertHHMMSSToTod(time) {
477
+ const h = Number(time.substring(0, 2));
478
+ const m = Number(time.substring(2, 4));
479
+ const s = Number(time.substring(4, 6));
480
+ const tod = h * 3600 + m * 60 + s;
481
+ return tod;
482
+ }
483
+ /**
484
+ *
485
+ * @param time HHMMSS
486
+ * @param date MMDDYY
487
+ * @returns seconds since epoch
488
+ */
489
+ static convertDateTimeToEpoch(time, date) {
490
+ const timestamp = `20${date.substring(4, 6)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
491
+ const millis = Date.parse(timestamp);
492
+ return millis / 1e3;
493
+ }
494
+ };
495
+
496
+ // lib/plugins/Label_1M_Slash.ts
497
+ var Label_1M_Slash = class extends DecoderPlugin {
498
+ name = "label-1m-slash";
499
+ qualifiers() {
500
+ return {
501
+ labels: ["1M"],
502
+ preambles: ["/"]
503
+ };
504
+ }
505
+ decode(message, options = {}) {
506
+ const decodeResult = this.defaultResult;
507
+ decodeResult.decoder.name = this.name;
508
+ decodeResult.formatted.description = "ETA Report";
509
+ decodeResult.message = message;
510
+ const results = message.text.split(/\n|\//).slice(1);
511
+ if (results) {
512
+ if (options.debug) {
513
+ console.log(`Label 1M ETA: results`);
514
+ console.log(results);
515
+ }
516
+ decodeResult.raw.flight_number = results[0];
517
+ decodeResult.raw.departure_icao = results[3];
518
+ decodeResult.raw.arrival_icao = results[4];
519
+ decodeResult.raw.alternate_icao = results[5];
520
+ decodeResult.raw.arrival_runway = results[8].replace(decodeResult.raw.arrival_icao, "");
521
+ decodeResult.formatted.items.push({
522
+ type: "eta",
523
+ code: "ETA",
524
+ label: "Estimated Time of Arrival",
525
+ value: DateTimeUtils.UTCDateTimeToString(results[2], results[7])
526
+ });
527
+ decodeResult.formatted.items.push({
528
+ type: "destination",
529
+ code: "DST",
530
+ label: "Destination",
531
+ value: decodeResult.raw.arrival_icao
532
+ });
533
+ decodeResult.formatted.items.push({
534
+ type: "origin",
535
+ code: "ORG",
536
+ label: "Origin",
537
+ value: decodeResult.raw.departure_icao
538
+ });
539
+ }
540
+ decodeResult.decoded = true;
541
+ decodeResult.decoder.decodeLevel = "partial";
542
+ return decodeResult;
543
+ }
544
+ };
545
+
546
+ // lib/plugins/Label_20_POS.ts
547
+ var Label_20_POS = class extends DecoderPlugin {
548
+ name = "label-20-pos";
549
+ qualifiers() {
550
+ return {
551
+ labels: ["20"],
552
+ preambles: ["POS"]
553
+ };
554
+ }
555
+ decode(message, options = {}) {
556
+ const decodeResult = this.defaultResult;
557
+ decodeResult.decoder.name = this.name;
558
+ decodeResult.formatted.description = "Position Report";
559
+ decodeResult.message = message;
560
+ decodeResult.raw.preamble = message.text.substring(0, 3);
561
+ const content = message.text.substring(3);
562
+ console.log("Content: " + content);
563
+ const fields = content.split(",");
564
+ console.log("Field Count: " + fields.length);
565
+ if (fields.length == 11) {
566
+ console.log(`DEBUG: ${this.name}: Variation 1 detected`);
567
+ const rawCoords = fields[0];
568
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(rawCoords);
569
+ if (decodeResult.raw.position) {
570
+ decodeResult.formatted.items.push({
571
+ type: "position",
572
+ label: "Position",
573
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
574
+ });
575
+ }
576
+ decodeResult.decoded = true;
577
+ decodeResult.decoder.decodeLevel = "full";
578
+ } else if (fields.length == 5) {
579
+ console.log(`DEBUG: ${this.name}: Variation 2 detected`);
580
+ const rawCoords = fields[0];
581
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(rawCoords);
582
+ decodeResult.formatted.items.push({
583
+ type: "position",
584
+ label: "Position",
585
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
586
+ });
587
+ decodeResult.decoded = true;
588
+ decodeResult.decoder.decodeLevel = "full";
589
+ } else {
590
+ console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${content}`);
591
+ decodeResult.decoded = false;
592
+ decodeResult.decoder.decodeLevel = "none";
593
+ }
594
+ return decodeResult;
595
+ }
596
+ };
597
+
598
+ // lib/plugins/Label_30_Slash_EA.ts
599
+ var Label_30_Slash_EA = class extends DecoderPlugin {
600
+ name = "label-30-slash-ea";
601
+ qualifiers() {
602
+ return {
603
+ labels: ["30"],
604
+ preambles: ["/EA"]
605
+ };
606
+ }
607
+ decode(message, options = {}) {
608
+ const decodeResult = this.defaultResult;
609
+ decodeResult.decoder.name = this.name;
610
+ decodeResult.formatted.description = "ETA Report";
611
+ decodeResult.message = message;
612
+ const results = message.text.split(/\n|\//).slice(1);
613
+ if (results) {
614
+ if (options.debug) {
615
+ console.log(`Label 30 EA: results`);
616
+ console.log(results);
617
+ }
618
+ }
619
+ decodeResult.formatted.items.push({
620
+ type: "eta",
621
+ code: "ETA",
622
+ label: "Estimated Time of Arrival",
623
+ value: DateTimeUtils.UTCToString(results[0].substr(2, 4))
624
+ });
625
+ if (results[1].substr(0, 2) === "DS") {
626
+ decodeResult.raw.arrival_icao = results[1].substr(2, 4);
627
+ decodeResult.formatted.items.push({
628
+ type: "destination",
629
+ code: "DST",
630
+ label: "Destination",
631
+ value: decodeResult.raw.arrival_icao
632
+ });
633
+ decodeResult.remaining.text = "/".concat(results[2]);
634
+ } else {
635
+ decodeResult.remaining.text = "/".concat(results[1], "/", results[2]);
636
+ }
637
+ decodeResult.decoded = true;
638
+ decodeResult.decoder.decodeLevel = "partial";
639
+ return decodeResult;
640
+ }
641
+ };
642
+
643
+ // lib/plugins/Label_44_ETA.ts
644
+ var Label_44_ETA = class extends DecoderPlugin {
645
+ name = "label-44-eta";
646
+ qualifiers() {
647
+ return {
648
+ labels: ["44"],
649
+ preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
650
+ };
651
+ }
652
+ decode(message, options = {}) {
653
+ const decodeResult = this.defaultResult;
654
+ decodeResult.decoder.name = this.name;
655
+ decodeResult.formatted.description = "ETA Report";
656
+ decodeResult.message = message;
657
+ const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
658
+ const results = message.text.match(regex);
659
+ if (results) {
660
+ if (options.debug) {
661
+ console.log(`Label 44 ETA Report: groups`);
662
+ console.log(results.groups);
663
+ }
664
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
665
+ decodeResult.raw.departure_icao = results.groups.departure_icao;
666
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
667
+ decodeResult.raw.current_time = Date.parse(
668
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
669
+ );
670
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
671
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
672
+ }
673
+ if (decodeResult.raw.position) {
674
+ decodeResult.formatted.items.push({
675
+ type: "position",
676
+ code: "POS",
677
+ label: "Position",
678
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
679
+ });
680
+ }
681
+ decodeResult.formatted.items.push({
682
+ type: "origin",
683
+ code: "ORG",
684
+ label: "Origin",
685
+ value: decodeResult.raw.departure_icao
686
+ });
687
+ decodeResult.formatted.items.push({
688
+ type: "destination",
689
+ code: "DST",
690
+ label: "Destination",
691
+ value: decodeResult.raw.arrival_icao
692
+ });
693
+ }
694
+ decodeResult.decoded = true;
695
+ decodeResult.decoder.decodeLevel = "full";
696
+ return decodeResult;
697
+ }
698
+ };
699
+
700
+ // lib/plugins/Label_44_IN.ts
701
+ var Label_44_IN = class extends DecoderPlugin {
702
+ name = "label-44-in";
703
+ qualifiers() {
704
+ return {
705
+ labels: ["44"],
706
+ preambles: ["00IN01", "00IN02", "00IN03", "IN01", "IN02", "IN03"]
707
+ };
708
+ }
709
+ decode(message, options = {}) {
710
+ const decodeResult = this.defaultResult;
711
+ decodeResult.decoder.name = this.name;
712
+ decodeResult.formatted.description = "In Air Report";
713
+ decodeResult.message = message;
714
+ const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
715
+ const results = message.text.match(regex);
716
+ if (results) {
717
+ if (options.debug) {
718
+ console.log(`Label 44 In Air Report: groups`);
719
+ console.log(results.groups);
720
+ }
721
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
722
+ decodeResult.raw.departure_icao = results.groups.departure_icao;
723
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
724
+ decodeResult.raw.current_time = Date.parse(
725
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
726
+ );
727
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
728
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
729
+ }
730
+ if (decodeResult.raw.position) {
731
+ decodeResult.formatted.items.push({
732
+ type: "position",
733
+ code: "POS",
734
+ label: "Position",
735
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
736
+ });
737
+ }
738
+ decodeResult.formatted.items.push({
739
+ type: "origin",
740
+ code: "ORG",
741
+ label: "Origin",
742
+ value: decodeResult.raw.departure_icao
743
+ });
744
+ decodeResult.formatted.items.push({
745
+ type: "destination",
746
+ code: "DST",
747
+ label: "Destination",
748
+ value: decodeResult.raw.arrival_icao
749
+ });
750
+ }
751
+ decodeResult.decoded = true;
752
+ decodeResult.decoder.decodeLevel = "full";
753
+ return decodeResult;
754
+ }
755
+ };
756
+
757
+ // lib/plugins/Label_44_OFF.ts
758
+ var Label_44_OFF = class extends DecoderPlugin {
759
+ name = "label-44-off";
760
+ qualifiers() {
761
+ return {
762
+ labels: ["44"],
763
+ preambles: ["00OFF01", "00OFF02", "00OFF03", "OFF01", "OFF02", "OFF03"]
764
+ };
765
+ }
766
+ decode(message, options = {}) {
767
+ const decodeResult = this.defaultResult;
768
+ decodeResult.decoder.name = this.name;
769
+ decodeResult.formatted.description = "Off Runway Report";
770
+ decodeResult.message = message;
771
+ const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
772
+ const results = message.text.match(regex);
773
+ if (results) {
774
+ if (options.debug) {
775
+ console.log(`Label 44 Off Runway Report: groups`);
776
+ console.log(results.groups);
777
+ }
778
+ decodeResult.raw.departure_icao = results.groups.departure_icao;
779
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
780
+ decodeResult.raw.current_time = Date.parse(
781
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
782
+ );
783
+ decodeResult.raw.eta_time = Date.parse(
784
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.eta_time.substr(0, 2) + ":" + results.groups.eta_time.substr(2, 2) + ":00Z"
785
+ );
786
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
787
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
788
+ }
789
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
790
+ if (decodeResult.raw.position) {
791
+ decodeResult.formatted.items.push({
792
+ type: "position",
793
+ code: "POS",
794
+ label: "Position",
795
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
796
+ });
797
+ }
798
+ decodeResult.formatted.items.push({
799
+ type: "origin",
800
+ code: "ORG",
801
+ label: "Origin",
802
+ value: decodeResult.raw.departure_icao
803
+ });
804
+ decodeResult.formatted.items.push({
805
+ type: "destination",
806
+ code: "DST",
807
+ label: "Destination",
808
+ value: decodeResult.raw.arrival_icao
809
+ });
810
+ }
811
+ decodeResult.decoded = true;
812
+ decodeResult.decoder.decodeLevel = "full";
813
+ return decodeResult;
814
+ }
815
+ };
816
+
817
+ // lib/plugins/Label_44_ON.ts
818
+ var Label_44_ON = class extends DecoderPlugin {
819
+ name = "label-44-on";
820
+ qualifiers() {
821
+ return {
822
+ labels: ["44"],
823
+ preambles: ["00ON01", "00ON02", "00ON03", "ON01", "ON02", "ON03"]
824
+ };
825
+ }
826
+ decode(message, options = {}) {
827
+ const decodeResult = this.defaultResult;
828
+ decodeResult.decoder.name = this.name;
829
+ decodeResult.formatted.description = "On Runway Report";
830
+ decodeResult.message = message;
831
+ const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
832
+ const results = message.text.match(regex);
833
+ if (results) {
834
+ if (options.debug) {
835
+ console.log(`Label 44 On Runway Report: groups`);
836
+ console.log(results.groups);
837
+ }
838
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
839
+ decodeResult.raw.departure_icao = results.groups.departure_icao;
840
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
841
+ decodeResult.raw.current_time = Date.parse(
842
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
843
+ );
844
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
845
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
846
+ }
847
+ if (decodeResult.raw.position) {
848
+ decodeResult.formatted.items.push({
849
+ type: "position",
850
+ code: "POS",
851
+ label: "Position",
852
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
853
+ });
854
+ }
855
+ decodeResult.formatted.items.push({
856
+ type: "origin",
857
+ code: "ORG",
858
+ label: "Origin",
859
+ value: decodeResult.raw.departure_icao
860
+ });
861
+ decodeResult.formatted.items.push({
862
+ type: "destination",
863
+ code: "DST",
864
+ label: "Destination",
865
+ value: decodeResult.raw.arrival_icao
866
+ });
867
+ }
868
+ decodeResult.decoded = true;
869
+ decodeResult.decoder.decodeLevel = "full";
870
+ return decodeResult;
871
+ }
872
+ };
873
+
874
+ // lib/plugins/Label_44_POS.ts
875
+ var Label_44_POS = class extends DecoderPlugin {
876
+ name = "label-44-pos";
877
+ qualifiers() {
878
+ return {
879
+ labels: ["44"],
880
+ preambles: ["00POS01", "00POS02", "00POS03", "POS01", "POS02", "POS03"]
881
+ };
882
+ }
883
+ decode(message, options = {}) {
884
+ const decodeResult = this.defaultResult;
885
+ decodeResult.decoder.name = this.name;
886
+ decodeResult.formatted.description = "Position Report";
887
+ decodeResult.message = message;
888
+ const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
889
+ const results = message.text.match(regex);
890
+ if (results) {
891
+ if (options.debug) {
892
+ console.log(`Label 44 Position Report: groups`);
893
+ console.log(results.groups);
894
+ }
895
+ decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
896
+ decodeResult.raw.flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? "0" : Number(results.groups.flight_level_or_ground);
897
+ decodeResult.raw.departure_icao = results.groups.departure_icao;
898
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
899
+ decodeResult.raw.current_time = Date.parse(
900
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
901
+ );
902
+ decodeResult.raw.eta_time = Date.parse(
903
+ (/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.eta_time.substr(0, 2) + ":" + results.groups.eta_time.substr(2, 2) + ":00Z"
904
+ );
905
+ if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
906
+ decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
907
+ }
908
+ if (decodeResult.raw.position) {
909
+ decodeResult.formatted.items.push({
910
+ type: "position",
911
+ code: "POS",
912
+ label: "Position",
913
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
914
+ });
915
+ }
916
+ decodeResult.formatted.items.push({
917
+ type: "origin",
918
+ code: "ORG",
919
+ label: "Origin",
920
+ value: decodeResult.raw.departure_icao
921
+ });
922
+ decodeResult.formatted.items.push({
923
+ type: "destination",
924
+ code: "DST",
925
+ label: "Destination",
926
+ value: decodeResult.raw.arrival_icao
927
+ });
928
+ decodeResult.formatted.items.push({
929
+ type: "flight_level",
930
+ code: "FL",
931
+ label: "Flight Level",
932
+ value: decodeResult.raw.flight_level
933
+ });
934
+ }
935
+ decodeResult.decoded = true;
936
+ decodeResult.decoder.decodeLevel = "full";
937
+ return decodeResult;
938
+ }
939
+ };
940
+
941
+ // lib/plugins/Label_80.ts
942
+ var Label_80 = class extends DecoderPlugin {
943
+ name = "label-80";
944
+ descriptions = {
945
+ ALT: "Altitude",
946
+ DWND: "Wind Direction",
947
+ ETA: "Estimated Time of Arrival",
948
+ FOB: "Fuel on Board",
949
+ FL: "Flight Level",
950
+ HDG: "Heading",
951
+ MCH: "Aircraft Speed",
952
+ NWYP: "Next Waypoint",
953
+ POS: "Aircraft Position",
954
+ SAT: "Static Air Temperature",
955
+ SWND: "Wind Speed",
956
+ TAS: "True Airspeed",
957
+ WYP: "Waypoint"
958
+ };
959
+ qualifiers() {
960
+ return {
961
+ labels: ["80"],
962
+ preambles: ["3N01 POSRPT"]
963
+ };
964
+ }
965
+ decode(message, options = {}) {
966
+ const decodeResult = this.defaultResult;
967
+ decodeResult.decoder.name = this.name;
968
+ decodeResult.formatted.description = "Airline Defined Position Report";
969
+ const parts = message.text.split("\n");
970
+ let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
971
+ let results = parts[0].match(posRptRegex);
972
+ if (results && results.length > 0) {
973
+ decodeResult.raw.origin = results.groups.orig;
974
+ decodeResult.formatted.items.push({
975
+ type: "origin",
976
+ code: "ORG",
977
+ label: "Origin",
978
+ value: `${results.groups.orig}`
979
+ });
980
+ decodeResult.raw.destination = results.groups.dest;
981
+ decodeResult.formatted.items.push({
982
+ type: "destination",
983
+ code: "DST",
984
+ label: "Destination",
985
+ value: `${results.groups.dest}`
986
+ });
987
+ decodeResult.raw.tail = results.groups.tail;
988
+ decodeResult.formatted.items.push({
989
+ type: "tail",
990
+ label: "Tail",
991
+ value: `${results.groups.tail}`
992
+ });
993
+ if (results.groups.agate) {
994
+ decodeResult.raw.arrival_gate = results.groups.agate;
995
+ decodeResult.formatted.items.push({
996
+ type: "arrival_gate",
997
+ code: "ARG",
998
+ label: "Arrival Gate",
999
+ value: `${results.groups.agate}`
1000
+ });
1001
+ decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
1002
+ decodeResult.formatted.items.push({
1003
+ type: "scheduled_time_of_arrival",
1004
+ code: "STA",
1005
+ label: "Scheduled Time of Arrival",
1006
+ value: `${results.groups.sta}`
1007
+ });
1008
+ }
1009
+ posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
1010
+ const remainingParts = parts.slice(1);
1011
+ for (const part of remainingParts) {
1012
+ const matches = part.matchAll(posRptRegex);
1013
+ for (const match of matches) {
1014
+ switch (match.groups.field) {
1015
+ case "ALT": {
1016
+ decodeResult.raw.altitude = match.groups.value;
1017
+ decodeResult.formatted.items.push({
1018
+ type: "altitude",
1019
+ code: "ALT",
1020
+ label: this.descriptions[match.groups.field],
1021
+ value: `${decodeResult.raw.altitude} feet`
1022
+ });
1023
+ break;
1024
+ }
1025
+ case "DWND": {
1026
+ decodeResult.raw.wind_direction = Number(match.groups.value);
1027
+ decodeResult.formatted.items.push({
1028
+ type: "wind_direction",
1029
+ code: "DWND",
1030
+ label: this.descriptions[match.groups.field],
1031
+ value: decodeResult.raw.wind_direction
1032
+ });
1033
+ break;
1034
+ }
1035
+ case "FL": {
1036
+ decodeResult.raw.flight_level = match.groups.value;
1037
+ decodeResult.formatted.items.push({
1038
+ type: "flight_level",
1039
+ code: "FL",
1040
+ label: this.descriptions[match.groups.field],
1041
+ value: decodeResult.raw.flight_level
1042
+ });
1043
+ break;
1044
+ }
1045
+ case "FOB": {
1046
+ decodeResult.raw.fuel_on_board = match.groups.value;
1047
+ decodeResult.formatted.items.push({
1048
+ type: "fuel_on_board",
1049
+ code: "FOB",
1050
+ label: this.descriptions[match.groups.field],
1051
+ value: decodeResult.raw.fuel_on_board
1052
+ });
1053
+ break;
1054
+ }
1055
+ case "HDG": {
1056
+ decodeResult.raw.heading = Number(match.groups.value);
1057
+ decodeResult.formatted.items.push({
1058
+ type: "heading",
1059
+ code: "HDG",
1060
+ label: this.descriptions[match.groups.field],
1061
+ value: decodeResult.raw.heading
1062
+ });
1063
+ break;
1064
+ }
1065
+ case "MCH": {
1066
+ decodeResult.raw.mach = match.groups.value / 1e3;
1067
+ decodeResult.formatted.items.push({
1068
+ type: "mach",
1069
+ code: "MCH",
1070
+ label: this.descriptions[match.groups.field],
1071
+ value: `${decodeResult.raw.mach} Mach`
1072
+ });
1073
+ break;
1074
+ }
1075
+ case "NWYP": {
1076
+ decodeResult.raw.next_waypoint = match.groups.value;
1077
+ decodeResult.formatted.items.push({
1078
+ type: "next_waypoint",
1079
+ code: "NWYP",
1080
+ label: this.descriptions[match.groups.field],
1081
+ value: decodeResult.raw.next_waypoint
1082
+ });
1083
+ break;
1084
+ }
1085
+ case "POS": {
1086
+ const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
1087
+ const posResult = match.groups.value.match(posRegex);
1088
+ const lat = Number(posResult.groups.lat) * (posResult.groups.lngd === "S" ? -1 : 1);
1089
+ const lon = Number(posResult.groups.lng) * (posResult.groups.lngd === "W" ? -1 : 1);
1090
+ const latitude = Number.isInteger(lat) ? lat / 1e3 : lat / 100;
1091
+ const longitude = Number.isInteger(lon) ? lon / 1e3 : lon / 100;
1092
+ decodeResult.raw.aircraft_position = {
1093
+ latitude,
1094
+ longitude
1095
+ };
1096
+ decodeResult.formatted.items.push({
1097
+ type: "position",
1098
+ code: "POS",
1099
+ label: "Position",
1100
+ value: `${Math.abs(latitude).toPrecision(5)} ${posResult.groups.latd}, ${Math.abs(longitude).toPrecision(5)} ${posResult.groups.lngd}`
1101
+ });
1102
+ break;
1103
+ }
1104
+ case "SWND": {
1105
+ decodeResult.raw.wind_speed = Number(match.groups.value);
1106
+ decodeResult.formatted.items.push({
1107
+ type: "wind_speed",
1108
+ code: "SWND",
1109
+ label: this.descriptions[match.groups.field],
1110
+ value: decodeResult.raw.wind_speed
1111
+ });
1112
+ break;
1113
+ }
1114
+ default: {
1115
+ if (match.groups.field != void 0) {
1116
+ const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
1117
+ decodeResult.formatted.items.push({
1118
+ type: match.groups.field,
1119
+ code: match.groups.field,
1120
+ label: description || `Unknown (${match.groups.field})`,
1121
+ value: `${match.groups.value}`
1122
+ });
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+ }
1128
+ decodeResult.decoded = true;
1129
+ decodeResult.decodeLevel = "partial";
1130
+ }
1131
+ return decodeResult;
1132
+ }
1133
+ };
1134
+
1135
+ // lib/plugins/Label_8E.ts
1136
+ var Label_8E = class extends DecoderPlugin {
1137
+ name = "label-8e";
1138
+ qualifiers() {
1139
+ return {
1140
+ labels: ["8E"]
1141
+ };
1142
+ }
1143
+ decode(message, options = {}) {
1144
+ const decodeResult = this.defaultResult;
1145
+ decodeResult.decoder.name = this.name;
1146
+ decodeResult.formatted.description = "ETA Report";
1147
+ decodeResult.message = message;
1148
+ const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
1149
+ const results = message.text.match(regex);
1150
+ if (results) {
1151
+ if (options.debug) {
1152
+ console.log(`Label 8E ETA: groups`);
1153
+ console.log(results.groups);
1154
+ }
1155
+ decodeResult.formatted.items.push({
1156
+ type: "eta",
1157
+ code: "ETA",
1158
+ label: "Estimated Time of Arrival",
1159
+ value: DateTimeUtils.UTCToString(results.groups.arrival_eta)
1160
+ });
1161
+ decodeResult.raw.arrival_icao = results.groups.arrival_icao;
1162
+ decodeResult.formatted.items.push({
1163
+ type: "destination",
1164
+ code: "DST",
1165
+ label: "Destination",
1166
+ value: decodeResult.raw.arrival_icao
1167
+ });
1168
+ }
1169
+ decodeResult.decoded = true;
1170
+ decodeResult.decoder.decodeLevel = "full";
1171
+ return decodeResult;
1172
+ }
1173
+ };
1174
+
1175
+ // lib/plugins/Label_B6.ts
1176
+ var Label_B6_Forwardslash = class extends DecoderPlugin {
1177
+ name = "label-b6-forwardslash";
1178
+ qualifiers() {
1179
+ return {
1180
+ labels: ["B6"],
1181
+ preambles: ["/"]
1182
+ };
1183
+ }
1184
+ decode(message, options = {}) {
1185
+ const decodeResult = this.defaultResult;
1186
+ decodeResult.decoder.name = this.name;
1187
+ decodeResult.formatted.description = "CPDLC Message";
1188
+ decodeResult.message = message;
1189
+ if (options.debug) {
1190
+ console.log("CPDLC: " + message);
1191
+ }
1192
+ return decodeResult;
1193
+ }
1194
+ };
1195
+
1196
+ // lib/plugins/Label_ColonComma.ts
1197
+ var Label_ColonComma = class extends DecoderPlugin {
1198
+ name = "label-colon-comma";
1199
+ qualifiers() {
1200
+ return {
1201
+ labels: [":;"]
1202
+ };
1203
+ }
1204
+ decode(message, options = {}) {
1205
+ const decodeResult = this.defaultResult;
1206
+ decodeResult.decoder.name = this.name;
1207
+ decodeResult.raw.frequency = Number(message.text) / 1e3;
1208
+ decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
1209
+ decodeResult.formatted.items.push({
1210
+ type: "frequency",
1211
+ label: "Frequency",
1212
+ value: `${decodeResult.raw.frequency} MHz`
1213
+ });
1214
+ decodeResult.decoded = true;
1215
+ decodeResult.decoder.decodeLevel = "full";
1216
+ return decodeResult;
1217
+ }
1218
+ };
1219
+
1220
+ // lib/utils/route_utils.ts
1221
+ var RouteUtils = class _RouteUtils {
1222
+ static routeToString(route) {
1223
+ let str = "";
1224
+ if (route.name) {
1225
+ str += route.name;
1226
+ }
1227
+ if (route.runway) {
1228
+ str += `(${route.runway})`;
1229
+ }
1230
+ if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
1231
+ str += " starting at ";
1232
+ } else if (str.length !== 0 && route.waypoints) {
1233
+ str += ": ";
1234
+ }
1235
+ if (route.waypoints) {
1236
+ str += _RouteUtils.waypointsToString(route.waypoints);
1237
+ }
1238
+ return str;
1239
+ }
1240
+ static waypointToString(waypoint) {
1241
+ let s = waypoint.name;
1242
+ if (waypoint.latitude && waypoint.longitude) {
1243
+ s += `(${CoordinateUtils.latLonToCoordinateString(waypoint.latitude, waypoint.longitude)})`;
1244
+ }
1245
+ if (waypoint.time && waypoint.timeFormat) {
1246
+ s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
1247
+ }
1248
+ return s;
1249
+ }
1250
+ static getWaypoint(leg) {
1251
+ const waypoint = leg.split(",");
1252
+ if (waypoint.length == 2) {
1253
+ const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1254
+ return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1255
+ }
1256
+ if (leg.length == 14) {
1257
+ const position = CoordinateUtils.decodeStringCoordinates(leg);
1258
+ return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1259
+ }
1260
+ return { name: leg };
1261
+ }
1262
+ // move out if we want public
1263
+ static timestampToString(time, format) {
1264
+ const date = new Date(time * 1e3);
1265
+ if (format == "tod") {
1266
+ return date.toISOString().slice(11, 19);
1267
+ }
1268
+ return date.toISOString().slice(0, -5) + "Z";
1269
+ }
1270
+ static waypointsToString(waypoints) {
1271
+ let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
1272
+ if (str.startsWith(" > ")) {
1273
+ str = ">>" + str.slice(2);
1274
+ }
1275
+ return str;
1276
+ }
1277
+ };
1278
+
1279
+ // lib/utils/flight_plan_utils.ts
1280
+ var FlightPlanUtils = class {
1281
+ /**
1282
+ * Processes flight plan data
1283
+ *
1284
+ * Expected format is [header, key1, val1, ... keyN, valN]
1285
+ *
1286
+ * @param decodeResult - results
1287
+ * @param data - original message split by ':'
1288
+ * @returns whether all fields were processed or not
1289
+ */
1290
+ static processFlightPlan(decodeResult, data) {
1291
+ let allKnownFields = parseHeader(decodeResult, data[0]);
1292
+ for (let i = 1; i < data.length; i += 2) {
1293
+ const key = data[i];
1294
+ const value = data[i + 1];
1295
+ switch (key) {
1296
+ case "A":
1297
+ addProcedure(decodeResult, value, "arrival");
1298
+ break;
1299
+ case "AA":
1300
+ addArrivalAirport(decodeResult, value);
1301
+ break;
1302
+ case "AP":
1303
+ addProcedure(decodeResult, value, "approach");
1304
+ break;
1305
+ case "CR":
1306
+ addCompanyRoute(decodeResult, value);
1307
+ break;
1308
+ case "D":
1309
+ addProcedure(decodeResult, value, "departure");
1310
+ break;
1311
+ case "DA":
1312
+ addDepartureAirport(decodeResult, value);
1313
+ break;
1314
+ case "F":
1315
+ addRoute(decodeResult, value);
1316
+ break;
1317
+ case "R":
1318
+ addDepartureRunway(decodeResult, value);
1319
+ break;
1320
+ default:
1321
+ if (allKnownFields) {
1322
+ decodeResult.remaining.text = "";
1323
+ allKnownFields = false;
1324
+ }
1325
+ decodeResult.remaining.text += `:${key}:${value}`;
1326
+ decodeResult.decoder.decodeLevel = "partial";
1327
+ }
1328
+ }
1329
+ return allKnownFields;
1330
+ }
1331
+ };
1332
+ function parseHeader(decodeResult, header) {
1333
+ let allKnownFields = true;
1334
+ const fields = header.split("/");
1335
+ for (let i = 1; i < fields.length - 1; ++i) {
1336
+ if (fields[i].startsWith("FN")) {
1337
+ decodeResult.raw.flight_number = fields[i].substring(2);
1338
+ } else if (fields[i].startsWith("SN")) {
1339
+ decodeResult.raw.serial_number = fields[i].substring(2);
1340
+ } else if (fields[i].startsWith("TS")) {
1341
+ const ts = fields[i].substring(2).split(",");
1342
+ decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1343
+ } else {
1344
+ decodeResult.remaining.text += "/" + fields[i];
1345
+ allKnownFields = false;
1346
+ }
1347
+ }
1348
+ decodeResult.raw.route_status = fields[fields.length - 1];
1349
+ var text;
1350
+ if (decodeResult.raw.route_status == "RP") {
1351
+ text = "Route Planned";
1352
+ } else if (decodeResult.raw.route_status == "RI") {
1353
+ text = "Route Inactive";
1354
+ } else if (decodeResult.raw.route_status == "RF") {
1355
+ text = "Route Filed";
1356
+ } else {
1357
+ text = decodeResult.raw.route_status;
1358
+ }
1359
+ decodeResult.formatted.items.push({
1360
+ type: "status",
1361
+ code: "ROUTE_STATUS",
1362
+ label: "Route Status",
1363
+ value: text
1364
+ });
1365
+ return allKnownFields;
1366
+ }
1367
+ function addArrivalAirport(decodeResult, value) {
1368
+ decodeResult.raw.arrival_icao = value;
1369
+ decodeResult.formatted.items.push({
1370
+ type: "destination",
1371
+ code: "DST",
1372
+ label: "Destination",
1373
+ value: decodeResult.raw.arrival_icao
1374
+ });
1375
+ }
1376
+ function addDepartureAirport(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
+ function addDepartureRunway(decodeResult, value) {
1386
+ decodeResult.raw.runway = value;
1387
+ decodeResult.formatted.items.push({
1388
+ type: "runway",
1389
+ label: "Runway",
1390
+ value: decodeResult.raw.runway
1391
+ });
1392
+ }
1393
+ function addRoute(decodeResult, value) {
1394
+ const route = value.split(".");
1395
+ decodeResult.raw.route = { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) };
1396
+ decodeResult.formatted.items.push({
1397
+ type: "aircraft_route",
1398
+ code: "ROUTE",
1399
+ label: "Aircraft Route",
1400
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1401
+ });
1402
+ }
1403
+ function addProcedure(decodeResult, value, type) {
1404
+ if (decodeResult.raw.procedures === void 0) {
1405
+ decodeResult.raw.procedures = [];
1406
+ }
1407
+ const data = value.split(".");
1408
+ let waypoints;
1409
+ if (data.length > 1) {
1410
+ waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1411
+ }
1412
+ const route = { name: data[0], waypoints };
1413
+ decodeResult.raw.procedures.push({ type, route });
1414
+ const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
1415
+ let procedureValue = route.name;
1416
+ decodeResult.formatted.items.push({
1417
+ type: `procedure`,
1418
+ code: "proc",
1419
+ label: `${procedureName} Procedure`,
1420
+ value: RouteUtils.routeToString(route)
1421
+ });
1422
+ }
1423
+ function addCompanyRoute(decodeResult, value) {
1424
+ const segments = value.split(".");
1425
+ const parens_idx = segments[0].indexOf("(");
1426
+ let name;
1427
+ let runway;
1428
+ if (parens_idx === -1) {
1429
+ name = segments[0];
1430
+ } else {
1431
+ name = segments[0].slice(0, parens_idx);
1432
+ runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
1433
+ }
1434
+ let waypoints;
1435
+ if (segments.length > 1) {
1436
+ waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
1437
+ }
1438
+ decodeResult.raw.company_route = {
1439
+ name,
1440
+ runway,
1441
+ waypoints
1442
+ };
1443
+ decodeResult.formatted.items.push({
1444
+ type: "company_route",
1445
+ code: "CR",
1446
+ label: "Company Route",
1447
+ value: RouteUtils.routeToString(decodeResult.raw.company_route)
1448
+ });
1449
+ }
1450
+
1451
+ // lib/plugins/Label_H1_FPN.ts
1452
+ var Label_H1_FPN = class extends DecoderPlugin {
1453
+ name = "label-h1-fpn";
1454
+ qualifiers() {
1455
+ return {
1456
+ labels: ["H1"],
1457
+ preambles: ["FPN", "#M1BFPN"]
1458
+ };
1459
+ }
1460
+ decode(message, options = {}) {
1461
+ let decodeResult = this.defaultResult;
1462
+ decodeResult.decoder.name = this.name;
1463
+ decodeResult.formatted.description = "Flight Plan";
1464
+ decodeResult.message = message;
1465
+ const msg = message.text.replace(/\n|\r/g, "");
1466
+ const checksum = msg.slice(-4);
1467
+ const data = msg.slice(0, msg.length - 4).split(":");
1468
+ if (data.length > 1) {
1469
+ const fulllyDecoded = FlightPlanUtils.processFlightPlan(decodeResult, data);
1470
+ addChecksum(decodeResult, checksum);
1471
+ decodeResult.decoded = true;
1472
+ decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
1473
+ } else {
1474
+ if (options?.debug) {
1475
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
1476
+ }
1477
+ decodeResult.remaining.text = message.text;
1478
+ decodeResult.decoded = false;
1479
+ decodeResult.decoder.decodeLevel = "none";
1480
+ }
1481
+ return decodeResult;
1482
+ }
1483
+ };
1484
+ function addChecksum(decodeResult, value) {
1485
+ decodeResult.raw.checksum = Number("0x" + value);
1486
+ decodeResult.formatted.items.push({
1487
+ type: "message_checksum",
1488
+ code: "CHECKSUM",
1489
+ label: "Message Checksum",
1490
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1491
+ });
1492
+ }
1493
+
1494
+ // lib/plugins/Label_H1_POS.ts
1495
+ var Label_H1_POS = class extends DecoderPlugin {
1496
+ name = "label-h1-pos";
1497
+ qualifiers() {
1498
+ return {
1499
+ labels: ["H1"],
1500
+ preambles: ["POS", "#M1BPOS"]
1501
+ //TODO - support data before #
1502
+ };
1503
+ }
1504
+ decode(message, options = {}) {
1505
+ let decodeResult = this.defaultResult;
1506
+ decodeResult.decoder.name = this.name;
1507
+ decodeResult.formatted.description = "Position Report";
1508
+ decodeResult.message = message;
1509
+ const checksum = message.text.slice(-4);
1510
+ const parts = message.text.replace("#M1B", "").replace("POS", "").slice(0, -4).split(",");
1511
+ console.log(parts);
1512
+ if (parts.length == 1 && parts[0].startsWith("/RF")) {
1513
+ decodeResult.raw.route_status == "RF";
1514
+ decodeResult.formatted.items.push({
1515
+ type: "status",
1516
+ code: "ROUTE_STATUS",
1517
+ label: "Route Status",
1518
+ value: "Route Filed"
1519
+ });
1520
+ decodeResult.raw.route = { waypoints: parts[0].substring(3, parts[0].length).split(".").map((leg) => RouteUtils.getWaypoint(leg)) };
1521
+ decodeResult.formatted.items.push({
1522
+ type: "aircraft_route",
1523
+ code: "ROUTE",
1524
+ label: "Aircraft Route",
1525
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1526
+ });
1527
+ processChecksum(decodeResult, checksum);
1528
+ decodeResult.decoded = true;
1529
+ decodeResult.decoder.decodeLevel = "full";
1530
+ } else if (parts.length === 10) {
1531
+ decodeResult.remaining.text = "";
1532
+ processPosition(decodeResult, parts[0]);
1533
+ processAlt(decodeResult, parts[3]);
1534
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1535
+ processTemp(decodeResult, parts[7]);
1536
+ processUnknown(decodeResult, parts[8]);
1537
+ processUnknown(decodeResult, parts[9]);
1538
+ processChecksum(decodeResult, checksum);
1539
+ decodeResult.decoded = true;
1540
+ decodeResult.decoder.decodeLevel = "partial";
1541
+ } else if (parts.length === 11) {
1542
+ decodeResult.remaining.text = "";
1543
+ processPosition(decodeResult, parts[0]);
1544
+ processAlt(decodeResult, parts[3]);
1545
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1546
+ processTemp(decodeResult, parts[7]);
1547
+ processUnknown(decodeResult, parts[8]);
1548
+ processUnknown(decodeResult, parts[9]);
1549
+ processChecksum(decodeResult, checksum);
1550
+ decodeResult.decoded = true;
1551
+ decodeResult.decoder.decodeLevel = "partial";
1552
+ } else if (parts.length === 14) {
1553
+ decodeResult.remaining.text = "";
1554
+ processPosition(decodeResult, parts[0]);
1555
+ processAlt(decodeResult, parts[3]);
1556
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1557
+ processTemp(decodeResult, parts[7]);
1558
+ processUnknown(decodeResult, parts[8]);
1559
+ processUnknown(decodeResult, parts[9]);
1560
+ processGndspd(decodeResult, parts[10]);
1561
+ processUnknown(decodeResult, parts[11]);
1562
+ processUnknown(decodeResult, parts[12]);
1563
+ processUnknown(decodeResult, parts[13]);
1564
+ processChecksum(decodeResult, checksum);
1565
+ decodeResult.decoded = true;
1566
+ decodeResult.decoder.decodeLevel = "partial";
1567
+ } else if (parts.length === 32) {
1568
+ decodeResult.remaining.text = "";
1569
+ processPosition(decodeResult, parts[0]);
1570
+ processRunway(decodeResult, parts[1]);
1571
+ const time = parts[2];
1572
+ processUnknown(decodeResult, parts[3]);
1573
+ const past = parts[4];
1574
+ processUnknown(decodeResult, parts[5]);
1575
+ const eta = parts[6];
1576
+ const next = parts[7];
1577
+ processUnknown(decodeResult, parts.slice(8, 14).join(","));
1578
+ processUnknown(decodeResult, parts[16]);
1579
+ processUnknown(decodeResult, parts[17]);
1580
+ processUnknown(decodeResult, parts[18]);
1581
+ processGndspd(decodeResult, parts[19]);
1582
+ processUnknown(decodeResult, parts[20]);
1583
+ processUnknown(decodeResult, parts[21]);
1584
+ processAlt(decodeResult, parts[22]);
1585
+ processUnknown(decodeResult, parts.slice(23, 31).join(","));
1586
+ const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1587
+ processRoute(decodeResult, past, time, next, eta, "?");
1588
+ decodeResult.decoded = true;
1589
+ decodeResult.decoder.decodeLevel = "partial";
1590
+ } else {
1591
+ if (options.debug) {
1592
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
1593
+ }
1594
+ decodeResult.remaining.text = message.text;
1595
+ decodeResult.decoded = false;
1596
+ decodeResult.decoder.decodeLevel = "none";
1597
+ }
1598
+ return decodeResult;
1599
+ }
1600
+ };
1601
+ function processUnknown(decodeResult, value) {
1602
+ decodeResult.remaining.text += "," + value;
1603
+ }
1604
+ function processPosition(decodeResult, value) {
1605
+ const position = CoordinateUtils.decodeStringCoordinates(value);
1606
+ decodeResult.raw.latitude_direction = position.latitudeDirection;
1607
+ decodeResult.raw.latitude = Math.abs(position.latitude);
1608
+ decodeResult.raw.longitude_direction = position.longitudeDirection;
1609
+ decodeResult.raw.longitude = Math.abs(position.longitude);
1610
+ decodeResult.formatted.items.push({
1611
+ type: "aircraft_position",
1612
+ code: "POS",
1613
+ label: "Aircraft Position",
1614
+ value: CoordinateUtils.coordinateString(position)
1615
+ });
1616
+ }
1617
+ function processAlt(decodeResult, value) {
1618
+ decodeResult.raw.altitude = Number(value) * 100;
1619
+ decodeResult.formatted.items.push({
1620
+ type: "altitude",
1621
+ code: "ALT",
1622
+ label: "Altitude",
1623
+ value: `${decodeResult.raw.altitude} feet`
1624
+ });
1625
+ }
1626
+ function processTemp(decodeResult, value) {
1627
+ decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
1628
+ decodeResult.formatted.items.push({
1629
+ type: "outside_air_temperature",
1630
+ code: "OATEMP",
1631
+ label: "Outside Air Temperature (C)",
1632
+ value: `${decodeResult.raw.outside_air_temperature}`
1633
+ });
1634
+ }
1635
+ function processRunway(decodeResult, value) {
1636
+ decodeResult.raw.runway = value.replace("RW", "");
1637
+ decodeResult.formatted.items.push({
1638
+ type: "runway",
1639
+ label: "Runway",
1640
+ value: decodeResult.raw.runway
1641
+ });
1642
+ }
1643
+ function processGndspd(decodeResult, value) {
1644
+ decodeResult.raw.groundspeed = Number(value);
1645
+ decodeResult.formatted.items.push({
1646
+ type: "aircraft_groundspeed",
1647
+ code: "GSPD",
1648
+ label: "Aircraft Groundspeed",
1649
+ value: `${decodeResult.raw.groundspeed}`
1650
+ });
1651
+ }
1652
+ function processRoute(decodeResult, last, time, next, eta, then, date) {
1653
+ let waypoints;
1654
+ waypoints = date === void 0 ? [
1655
+ { name: last || "?,", time: DateTimeUtils.convertHHMMSSToTod(time), timeFormat: "tod" },
1656
+ { name: next || "?", time: DateTimeUtils.convertHHMMSSToTod(eta), timeFormat: "tod" },
1657
+ { name: then || "?" }
1658
+ ] : [
1659
+ { name: last || "?,", time: DateTimeUtils.convertDateTimeToEpoch(time, date), timeFormat: "epoch" },
1660
+ { name: next || "?", time: DateTimeUtils.convertDateTimeToEpoch(eta, date), timeFormat: "epoch" },
1661
+ { name: then || "?" }
1662
+ ];
1663
+ decodeResult.raw.route = { waypoints };
1664
+ decodeResult.formatted.items.push({
1665
+ type: "aircraft_route",
1666
+ code: "ROUTE",
1667
+ label: "Aircraft Route",
1668
+ value: RouteUtils.routeToString(decodeResult.raw.route)
1669
+ });
1670
+ }
1671
+ function processChecksum(decodeResult, value) {
1672
+ decodeResult.raw.checksum = Number("0x" + value);
1673
+ decodeResult.formatted.items.push({
1674
+ type: "message_checksum",
1675
+ code: "CHECKSUM",
1676
+ label: "Message Checksum",
1677
+ value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1678
+ });
1679
+ }
1680
+
1681
+ // lib/plugins/Label_SQ.ts
1682
+ var Label_SQ = class extends DecoderPlugin {
1683
+ name = "label-sq";
1684
+ qualifiers() {
1685
+ return {
1686
+ labels: ["SQ"]
1687
+ };
1688
+ }
1689
+ decode(message, options = {}) {
1690
+ const decodeResult = this.defaultResult;
1691
+ decodeResult.decoder.name = this.name;
1692
+ decodeResult.raw.preamble = message.text.substring(0, 4);
1693
+ decodeResult.raw.version = message.text.substring(1, 2);
1694
+ decodeResult.raw.network = message.text.substring(3, 4);
1695
+ if (decodeResult.raw.version === "2") {
1696
+ const regex = /0(\d)X(?<org>\w)(?<iata>\w\w\w)(?<icao>\w\w\w\w)(?<station>\d)(?<lat>\d+)(?<latd>[NS])(?<lng>\d+)(?<lngd>[EW])V(?<vfreq>\d+)\/.*/;
1697
+ const result = message.text.match(regex);
1698
+ if (result && result.length >= 8) {
1699
+ decodeResult.raw.groundStation = {
1700
+ number: result.groups.station,
1701
+ iataCode: result.groups.iata,
1702
+ icaoCode: result.groups.icao,
1703
+ coordinates: {
1704
+ latitude: Number(result.groups.lat) / 100 * (result.groups.latd === "S" ? -1 : 1),
1705
+ longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
1706
+ }
1707
+ };
1708
+ decodeResult.raw.vdlFrequency = result.groups.vfreq / 1e3;
1709
+ }
1710
+ }
1711
+ decodeResult.formatted.description = "Ground Station Squitter";
1712
+ var formattedNetwork = "Unknown";
1713
+ if (decodeResult.raw.network == "A") {
1714
+ formattedNetwork = "ARINC";
1715
+ } else if (decodeResult.raw.network == "S") {
1716
+ formattedNetwork = "SITA";
1717
+ }
1718
+ decodeResult.formatted.items = [
1719
+ {
1720
+ type: "network",
1721
+ label: "Network",
1722
+ value: formattedNetwork
1723
+ },
1724
+ {
1725
+ type: "version",
1726
+ label: "Version",
1727
+ value: decodeResult.raw.version
1728
+ }
1729
+ ];
1730
+ if (decodeResult.raw.groundStation) {
1731
+ if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
1732
+ decodeResult.formatted.items.push({
1733
+ type: "ground_station",
1734
+ label: "Ground Station",
1735
+ value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
1736
+ });
1737
+ }
1738
+ if (decodeResult.raw.groundStation.iataCode) {
1739
+ decodeResult.formatted.items.push({
1740
+ type: "iataCode",
1741
+ label: "IATA",
1742
+ value: decodeResult.raw.groundStation.iataCode
1743
+ });
1744
+ }
1745
+ if (decodeResult.raw.groundStation.icaoCode) {
1746
+ decodeResult.formatted.items.push({
1747
+ type: "icaoCode",
1748
+ label: "ICAO",
1749
+ value: decodeResult.raw.groundStation.icaoCode
1750
+ });
1751
+ }
1752
+ if (decodeResult.raw.groundStation.coordinates.latitude) {
1753
+ decodeResult.formatted.items.push({
1754
+ type: "coordinates",
1755
+ label: "Ground Station Location",
1756
+ value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
1757
+ });
1758
+ }
1759
+ if (decodeResult.raw.groundStation.airport) {
1760
+ decodeResult.formatted.items.push({
1761
+ type: "airport",
1762
+ label: "Airport",
1763
+ value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
1764
+ });
1765
+ }
1766
+ }
1767
+ if (decodeResult.raw.vdlFrequency) {
1768
+ decodeResult.formatted.items.push({
1769
+ type: "vdlFrequency",
1770
+ label: "VDL Frequency",
1771
+ value: `${decodeResult.raw.vdlFrequency} MHz`
1772
+ });
1773
+ }
1774
+ decodeResult.decoded = true;
1775
+ decodeResult.decoder.decodeLevel = "full";
1776
+ return decodeResult;
1777
+ }
1778
+ };
1779
+
1780
+ // lib/plugins/Label_QR.ts
1781
+ var Label_QR = class extends DecoderPlugin {
1782
+ name = "label-qr";
1783
+ qualifiers() {
1784
+ return {
1785
+ labels: ["QR"]
1786
+ };
1787
+ }
1788
+ decode(message, options = {}) {
1789
+ const decodeResult = this.defaultResult;
1790
+ decodeResult.decoder.name = this.name;
1791
+ decodeResult.raw.origin = message.text.substring(0, 4);
1792
+ decodeResult.raw.destination = message.text.substring(4, 8);
1793
+ decodeResult.raw.wheels_on = message.text.substring(8, 12);
1794
+ decodeResult.remaining.text = message.text.substring(12);
1795
+ decodeResult.formatted.description = "ON Report";
1796
+ decodeResult.formatted.items = [
1797
+ {
1798
+ type: "origin",
1799
+ code: "ORG",
1800
+ label: "Origin",
1801
+ value: decodeResult.raw.origin
1802
+ },
1803
+ {
1804
+ type: "destination",
1805
+ code: "DST",
1806
+ label: "Destination",
1807
+ value: decodeResult.raw.destination
1808
+ },
1809
+ {
1810
+ type: "wheels_on",
1811
+ code: "WON",
1812
+ label: "Wheels ON",
1813
+ value: decodeResult.raw.wheels_on
1814
+ }
1815
+ ];
1816
+ decodeResult.decoded = true;
1817
+ if (decodeResult.remaining.text === "")
1818
+ decodeResult.decoder.decodeLevel = "full";
1819
+ else
1820
+ decodeResult.decoder.decodeLevel = "partial";
1821
+ return decodeResult;
1822
+ }
1823
+ };
1824
+
1825
+ // lib/plugins/Label_QP.ts
1826
+ var Label_QP = class extends DecoderPlugin {
1827
+ name = "label-qp";
1828
+ qualifiers() {
1829
+ return {
1830
+ labels: ["QP"]
1831
+ };
1832
+ }
1833
+ decode(message, options = {}) {
1834
+ const decodeResult = this.defaultResult;
1835
+ decodeResult.decoder.name = this.name;
1836
+ decodeResult.raw.origin = message.text.substring(0, 4);
1837
+ decodeResult.raw.destination = message.text.substring(4, 8);
1838
+ decodeResult.raw.gate_out = message.text.substring(8, 12);
1839
+ decodeResult.remaining.text = message.text.substring(12);
1840
+ decodeResult.formatted.description = "OUT Report";
1841
+ decodeResult.formatted.items = [
1842
+ {
1843
+ type: "origin",
1844
+ code: "ORG",
1845
+ label: "Origin",
1846
+ value: decodeResult.raw.origin
1847
+ },
1848
+ {
1849
+ type: "destination",
1850
+ code: "DST",
1851
+ label: "Destination",
1852
+ value: decodeResult.raw.destination
1853
+ },
1854
+ {
1855
+ type: "gate_out",
1856
+ code: "GOUT",
1857
+ label: "Gate OUT",
1858
+ value: decodeResult.raw.gate_out
1859
+ }
1860
+ ];
1861
+ decodeResult.decoded = true;
1862
+ if (decodeResult.remaining.text === "")
1863
+ decodeResult.decoder.decodeLevel = "full";
1864
+ else
1865
+ decodeResult.decoder.decodeLevel = "partial";
1866
+ return decodeResult;
1867
+ }
1868
+ };
1869
+
1870
+ // lib/plugins/Label_QS.ts
1871
+ var Label_QS = class extends DecoderPlugin {
1872
+ name = "label-qs";
1873
+ qualifiers() {
1874
+ return {
1875
+ labels: ["QS"]
1876
+ };
1877
+ }
1878
+ decode(message, options = {}) {
1879
+ const decodeResult = this.defaultResult;
1880
+ decodeResult.decoder.name = this.name;
1881
+ decodeResult.raw.origin = message.text.substring(0, 4);
1882
+ decodeResult.raw.destination = message.text.substring(4, 8);
1883
+ decodeResult.raw.gate_in = message.text.substring(8, 12);
1884
+ decodeResult.remaining.text = message.text.substring(12);
1885
+ decodeResult.formatted.description = "IN Report";
1886
+ decodeResult.formatted.items = [
1887
+ {
1888
+ type: "origin",
1889
+ code: "ORG",
1890
+ label: "Origin",
1891
+ value: decodeResult.raw.origin
1892
+ },
1893
+ {
1894
+ type: "destination",
1895
+ code: "DST",
1896
+ label: "Destination",
1897
+ value: decodeResult.raw.destination
1898
+ },
1899
+ {
1900
+ type: "gate_in",
1901
+ code: "GIN",
1902
+ label: "Gate IN",
1903
+ value: decodeResult.raw.gate_in
1904
+ }
1905
+ ];
1906
+ decodeResult.decoded = true;
1907
+ if (decodeResult.remaining.text === "")
1908
+ decodeResult.decoder.decodeLevel = "full";
1909
+ else
1910
+ decodeResult.decoder.decodeLevel = "partial";
1911
+ return decodeResult;
1912
+ }
1913
+ };
1914
+
1915
+ // lib/plugins/Label_QQ.ts
1916
+ var Label_QQ = class extends DecoderPlugin {
1917
+ name = "label-qq";
1918
+ qualifiers() {
1919
+ return {
1920
+ labels: ["QQ"]
1921
+ };
1922
+ }
1923
+ decode(message, options = {}) {
1924
+ const decodeResult = this.defaultResult;
1925
+ decodeResult.decoder.name = this.name;
1926
+ decodeResult.raw.origin = message.text.substring(0, 4);
1927
+ decodeResult.raw.destination = message.text.substring(4, 8);
1928
+ decodeResult.raw.wheels_off = message.text.substring(8, 12);
1929
+ decodeResult.remaining.text = message.text.substring(12);
1930
+ decodeResult.formatted.description = "OFF Report";
1931
+ decodeResult.formatted.items = [
1932
+ {
1933
+ type: "origin",
1934
+ code: "ORG",
1935
+ label: "Origin",
1936
+ value: decodeResult.raw.origin
1937
+ },
1938
+ {
1939
+ type: "destination",
1940
+ code: "DST",
1941
+ label: "Destination",
1942
+ value: decodeResult.raw.destination
1943
+ },
1944
+ {
1945
+ type: "wheels_off",
1946
+ code: "WOFF",
1947
+ label: "Wheels OFF",
1948
+ value: decodeResult.raw.wheels_off
1949
+ }
1950
+ ];
1951
+ decodeResult.decoded = true;
1952
+ if (decodeResult.remaining.text === "")
1953
+ decodeResult.decoder.decodeLevel = "full";
1954
+ else
1955
+ decodeResult.decoder.decodeLevel = "partial";
1956
+ return decodeResult;
1957
+ }
1958
+ };
1959
+
1960
+ // lib/utils/miam.ts
1961
+ var Base85 = __toESM(require("base85"));
1962
+ var Zlib = __toESM(require("zlib"));
1963
+ var MIAMCoreV1CRCLength = 4;
1964
+ var MIAMCoreV2CRCLength = 2;
1965
+ var MIAMCoreUtils = class {
1966
+ static AppTypeToAppIdLenTable = {
1967
+ 1: {
1968
+ [0 /* ACARS2Char */]: 2,
1969
+ [1 /* ACARS4Char */]: 4,
1970
+ [2 /* ACARS6Char */]: 6,
1971
+ [3 /* NonACARS6Char */]: 6
1972
+ },
1973
+ 2: {
1974
+ [0 /* ACARS2Char */]: 2,
1975
+ [1 /* ACARS4Char */]: 4,
1976
+ [2 /* ACARS6Char */]: 6,
1977
+ [3 /* NonACARS6Char */]: 6
1978
+ }
1979
+ };
1980
+ static FidHandlerTable = {
1981
+ ["T" /* SingleTransfer */]: (txt) => {
1982
+ if (txt.length < 3) {
1983
+ return {
1984
+ decoded: false,
1985
+ error: "Raw MIAM message too short (" + txt.length + " < 3) "
1986
+ };
1987
+ }
1988
+ let bpad = txt[0];
1989
+ if ("0123-.".indexOf(bpad) === -1) {
1990
+ return {
1991
+ decoded: false,
1992
+ error: "Invalid body padding value: '" + bpad + "'"
1993
+ };
1994
+ }
1995
+ if ("0123".indexOf(txt[1]) === -1) {
1996
+ return {
1997
+ decoded: false,
1998
+ error: "Invalid header padding value: '" + txt[1] + "'"
1999
+ };
2000
+ }
2001
+ const hpad = parseInt(txt[1]);
2002
+ const delimIdx = txt.indexOf("|");
2003
+ if (delimIdx === -1) {
2004
+ return {
2005
+ decoded: false,
2006
+ error: "Raw MIAM message missing header-body delimiter"
2007
+ };
2008
+ }
2009
+ const rawHdr = txt.substring(2, delimIdx);
2010
+ if (rawHdr.length === 0) {
2011
+ return {
2012
+ decoded: false,
2013
+ error: "Empty MIAM message header"
2014
+ };
2015
+ }
2016
+ let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
2017
+ if (!hdr || hdr.length < hpad) {
2018
+ return {
2019
+ decoded: false,
2020
+ error: "Ascii85 decode failed for MIAM message header"
2021
+ };
2022
+ }
2023
+ let body = void 0;
2024
+ const rawBody = txt.substring(delimIdx + 1);
2025
+ if (rawBody.length > 0) {
2026
+ if ("0123".indexOf(bpad) >= 0) {
2027
+ const bpadValue = parseInt(bpad);
2028
+ body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
2029
+ if (body && body.length >= bpadValue) {
2030
+ body = body.subarray(0, body.length - bpadValue);
2031
+ }
2032
+ } else if (bpad === "-") {
2033
+ body = Buffer.from(rawBody);
2034
+ }
2035
+ }
2036
+ hdr = hdr.subarray(0, hdr.length - hpad);
2037
+ const version = hdr.readUInt8(0) & 15;
2038
+ const pduType = hdr.readUInt8(0) >> 4 & 15;
2039
+ const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
2040
+ if (versionPduHandler === void 0) {
2041
+ return {
2042
+ decoded: false,
2043
+ error: "Invalid version and PDU type combination: v=" + version + ", pdu=" + pduType
2044
+ };
2045
+ }
2046
+ return versionPduHandler(hdr, body);
2047
+ },
2048
+ ["F" /* FileTransferRequest */]: void 0,
2049
+ ["K" /* FileTransferAccept */]: void 0,
2050
+ ["S" /* FileSegment */]: void 0,
2051
+ ["A" /* FileTransferAbort */]: void 0,
2052
+ ["Y" /* XOFFIndication */]: void 0,
2053
+ ["X" /* XONIndication */]: void 0
2054
+ };
2055
+ static arincCrc16(buf, seed) {
2056
+ const crctable = [
2057
+ 0,
2058
+ 4129,
2059
+ 8258,
2060
+ 12387,
2061
+ 16516,
2062
+ 20645,
2063
+ 24774,
2064
+ 28903,
2065
+ 33032,
2066
+ 37161,
2067
+ 41290,
2068
+ 45419,
2069
+ 49548,
2070
+ 53677,
2071
+ 57806,
2072
+ 61935,
2073
+ 4657,
2074
+ 528,
2075
+ 12915,
2076
+ 8786,
2077
+ 21173,
2078
+ 17044,
2079
+ 29431,
2080
+ 25302,
2081
+ 37689,
2082
+ 33560,
2083
+ 45947,
2084
+ 41818,
2085
+ 54205,
2086
+ 50076,
2087
+ 62463,
2088
+ 58334,
2089
+ 9314,
2090
+ 13379,
2091
+ 1056,
2092
+ 5121,
2093
+ 25830,
2094
+ 29895,
2095
+ 17572,
2096
+ 21637,
2097
+ 42346,
2098
+ 46411,
2099
+ 34088,
2100
+ 38153,
2101
+ 58862,
2102
+ 62927,
2103
+ 50604,
2104
+ 54669,
2105
+ 13907,
2106
+ 9842,
2107
+ 5649,
2108
+ 1584,
2109
+ 30423,
2110
+ 26358,
2111
+ 22165,
2112
+ 18100,
2113
+ 46939,
2114
+ 42874,
2115
+ 38681,
2116
+ 34616,
2117
+ 63455,
2118
+ 59390,
2119
+ 55197,
2120
+ 51132,
2121
+ 18628,
2122
+ 22757,
2123
+ 26758,
2124
+ 30887,
2125
+ 2112,
2126
+ 6241,
2127
+ 10242,
2128
+ 14371,
2129
+ 51660,
2130
+ 55789,
2131
+ 59790,
2132
+ 63919,
2133
+ 35144,
2134
+ 39273,
2135
+ 43274,
2136
+ 47403,
2137
+ 23285,
2138
+ 19156,
2139
+ 31415,
2140
+ 27286,
2141
+ 6769,
2142
+ 2640,
2143
+ 14899,
2144
+ 10770,
2145
+ 56317,
2146
+ 52188,
2147
+ 64447,
2148
+ 60318,
2149
+ 39801,
2150
+ 35672,
2151
+ 47931,
2152
+ 43802,
2153
+ 27814,
2154
+ 31879,
2155
+ 19684,
2156
+ 23749,
2157
+ 11298,
2158
+ 15363,
2159
+ 3168,
2160
+ 7233,
2161
+ 60846,
2162
+ 64911,
2163
+ 52716,
2164
+ 56781,
2165
+ 44330,
2166
+ 48395,
2167
+ 36200,
2168
+ 40265,
2169
+ 32407,
2170
+ 28342,
2171
+ 24277,
2172
+ 20212,
2173
+ 15891,
2174
+ 11826,
2175
+ 7761,
2176
+ 3696,
2177
+ 65439,
2178
+ 61374,
2179
+ 57309,
2180
+ 53244,
2181
+ 48923,
2182
+ 44858,
2183
+ 40793,
2184
+ 36728,
2185
+ 37256,
2186
+ 33193,
2187
+ 45514,
2188
+ 41451,
2189
+ 53516,
2190
+ 49453,
2191
+ 61774,
2192
+ 57711,
2193
+ 4224,
2194
+ 161,
2195
+ 12482,
2196
+ 8419,
2197
+ 20484,
2198
+ 16421,
2199
+ 28742,
2200
+ 24679,
2201
+ 33721,
2202
+ 37784,
2203
+ 41979,
2204
+ 46042,
2205
+ 49981,
2206
+ 54044,
2207
+ 58239,
2208
+ 62302,
2209
+ 689,
2210
+ 4752,
2211
+ 8947,
2212
+ 13010,
2213
+ 16949,
2214
+ 21012,
2215
+ 25207,
2216
+ 29270,
2217
+ 46570,
2218
+ 42443,
2219
+ 38312,
2220
+ 34185,
2221
+ 62830,
2222
+ 58703,
2223
+ 54572,
2224
+ 50445,
2225
+ 13538,
2226
+ 9411,
2227
+ 5280,
2228
+ 1153,
2229
+ 29798,
2230
+ 25671,
2231
+ 21540,
2232
+ 17413,
2233
+ 42971,
2234
+ 47098,
2235
+ 34713,
2236
+ 38840,
2237
+ 59231,
2238
+ 63358,
2239
+ 50973,
2240
+ 55100,
2241
+ 9939,
2242
+ 14066,
2243
+ 1681,
2244
+ 5808,
2245
+ 26199,
2246
+ 30326,
2247
+ 17941,
2248
+ 22068,
2249
+ 55628,
2250
+ 51565,
2251
+ 63758,
2252
+ 59695,
2253
+ 39368,
2254
+ 35305,
2255
+ 47498,
2256
+ 43435,
2257
+ 22596,
2258
+ 18533,
2259
+ 30726,
2260
+ 26663,
2261
+ 6336,
2262
+ 2273,
2263
+ 14466,
2264
+ 10403,
2265
+ 52093,
2266
+ 56156,
2267
+ 60223,
2268
+ 64286,
2269
+ 35833,
2270
+ 39896,
2271
+ 43963,
2272
+ 48026,
2273
+ 19061,
2274
+ 23124,
2275
+ 27191,
2276
+ 31254,
2277
+ 2801,
2278
+ 6864,
2279
+ 10931,
2280
+ 14994,
2281
+ 64814,
2282
+ 60687,
2283
+ 56684,
2284
+ 52557,
2285
+ 48554,
2286
+ 44427,
2287
+ 40424,
2288
+ 36297,
2289
+ 31782,
2290
+ 27655,
2291
+ 23652,
2292
+ 19525,
2293
+ 15522,
2294
+ 11395,
2295
+ 7392,
2296
+ 3265,
2297
+ 61215,
2298
+ 65342,
2299
+ 53085,
2300
+ 57212,
2301
+ 44955,
2302
+ 49082,
2303
+ 36825,
2304
+ 40952,
2305
+ 28183,
2306
+ 32310,
2307
+ 20053,
2308
+ 24180,
2309
+ 11923,
2310
+ 16050,
2311
+ 3793,
2312
+ 7920
2313
+ ];
2314
+ let crc = (seed || 0) & 65535;
2315
+ for (let i = 0; i < buf.length; i++) {
2316
+ crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf.readUInt8(i)) >>> 0 & 255]) >>> 0;
2317
+ }
2318
+ return crc & 65535;
2319
+ }
2320
+ static arinc665Crc32(buf, seed) {
2321
+ const crctable = [
2322
+ 0,
2323
+ 79764919,
2324
+ 159529838,
2325
+ 222504665,
2326
+ 319059676,
2327
+ 398814059,
2328
+ 445009330,
2329
+ 507990021,
2330
+ 638119352,
2331
+ 583659535,
2332
+ 797628118,
2333
+ 726387553,
2334
+ 890018660,
2335
+ 835552979,
2336
+ 1015980042,
2337
+ 944750013,
2338
+ 1276238704,
2339
+ 1221641927,
2340
+ 1167319070,
2341
+ 1095957929,
2342
+ 1595256236,
2343
+ 1540665371,
2344
+ 1452775106,
2345
+ 1381403509,
2346
+ 1780037320,
2347
+ 1859660671,
2348
+ 1671105958,
2349
+ 1733955601,
2350
+ 2031960084,
2351
+ 2111593891,
2352
+ 1889500026,
2353
+ 1952343757,
2354
+ 2552477408,
2355
+ 2632100695,
2356
+ 2443283854,
2357
+ 2506133561,
2358
+ 2334638140,
2359
+ 2414271883,
2360
+ 2191915858,
2361
+ 2254759653,
2362
+ 3190512472,
2363
+ 3135915759,
2364
+ 3081330742,
2365
+ 3009969537,
2366
+ 2905550212,
2367
+ 2850959411,
2368
+ 2762807018,
2369
+ 2691435357,
2370
+ 3560074640,
2371
+ 3505614887,
2372
+ 3719321342,
2373
+ 3648080713,
2374
+ 3342211916,
2375
+ 3287746299,
2376
+ 3467911202,
2377
+ 3396681109,
2378
+ 4063920168,
2379
+ 4143685023,
2380
+ 4223187782,
2381
+ 4286162673,
2382
+ 3779000052,
2383
+ 3858754371,
2384
+ 3904687514,
2385
+ 3967668269,
2386
+ 881225847,
2387
+ 809987520,
2388
+ 1023691545,
2389
+ 969234094,
2390
+ 662832811,
2391
+ 591600412,
2392
+ 771767749,
2393
+ 717299826,
2394
+ 311336399,
2395
+ 374308984,
2396
+ 453813921,
2397
+ 533576470,
2398
+ 25881363,
2399
+ 88864420,
2400
+ 134795389,
2401
+ 214552010,
2402
+ 2023205639,
2403
+ 2086057648,
2404
+ 1897238633,
2405
+ 1976864222,
2406
+ 1804852699,
2407
+ 1867694188,
2408
+ 1645340341,
2409
+ 1724971778,
2410
+ 1587496639,
2411
+ 1516133128,
2412
+ 1461550545,
2413
+ 1406951526,
2414
+ 1302016099,
2415
+ 1230646740,
2416
+ 1142491917,
2417
+ 1087903418,
2418
+ 2896545431,
2419
+ 2825181984,
2420
+ 2770861561,
2421
+ 2716262478,
2422
+ 3215044683,
2423
+ 3143675388,
2424
+ 3055782693,
2425
+ 3001194130,
2426
+ 2326604591,
2427
+ 2389456536,
2428
+ 2200899649,
2429
+ 2280525302,
2430
+ 2578013683,
2431
+ 2640855108,
2432
+ 2418763421,
2433
+ 2498394922,
2434
+ 3769900519,
2435
+ 3832873040,
2436
+ 3912640137,
2437
+ 3992402750,
2438
+ 4088425275,
2439
+ 4151408268,
2440
+ 4197601365,
2441
+ 4277358050,
2442
+ 3334271071,
2443
+ 3263032808,
2444
+ 3476998961,
2445
+ 3422541446,
2446
+ 3585640067,
2447
+ 3514407732,
2448
+ 3694837229,
2449
+ 3640369242,
2450
+ 1762451694,
2451
+ 1842216281,
2452
+ 1619975040,
2453
+ 1682949687,
2454
+ 2047383090,
2455
+ 2127137669,
2456
+ 1938468188,
2457
+ 2001449195,
2458
+ 1325665622,
2459
+ 1271206113,
2460
+ 1183200824,
2461
+ 1111960463,
2462
+ 1543535498,
2463
+ 1489069629,
2464
+ 1434599652,
2465
+ 1363369299,
2466
+ 622672798,
2467
+ 568075817,
2468
+ 748617968,
2469
+ 677256519,
2470
+ 907627842,
2471
+ 853037301,
2472
+ 1067152940,
2473
+ 995781531,
2474
+ 51762726,
2475
+ 131386257,
2476
+ 177728840,
2477
+ 240578815,
2478
+ 269590778,
2479
+ 349224269,
2480
+ 429104020,
2481
+ 491947555,
2482
+ 4046411278,
2483
+ 4126034873,
2484
+ 4172115296,
2485
+ 4234965207,
2486
+ 3794477266,
2487
+ 3874110821,
2488
+ 3953728444,
2489
+ 4016571915,
2490
+ 3609705398,
2491
+ 3555108353,
2492
+ 3735388376,
2493
+ 3664026991,
2494
+ 3290680682,
2495
+ 3236090077,
2496
+ 3449943556,
2497
+ 3378572211,
2498
+ 3174993278,
2499
+ 3120533705,
2500
+ 3032266256,
2501
+ 2961025959,
2502
+ 2923101090,
2503
+ 2868635157,
2504
+ 2813903052,
2505
+ 2742672763,
2506
+ 2604032198,
2507
+ 2683796849,
2508
+ 2461293480,
2509
+ 2524268063,
2510
+ 2284983834,
2511
+ 2364738477,
2512
+ 2175806836,
2513
+ 2238787779,
2514
+ 1569362073,
2515
+ 1498123566,
2516
+ 1409854455,
2517
+ 1355396672,
2518
+ 1317987909,
2519
+ 1246755826,
2520
+ 1192025387,
2521
+ 1137557660,
2522
+ 2072149281,
2523
+ 2135122070,
2524
+ 1912620623,
2525
+ 1992383480,
2526
+ 1753615357,
2527
+ 1816598090,
2528
+ 1627664531,
2529
+ 1707420964,
2530
+ 295390185,
2531
+ 358241886,
2532
+ 404320391,
2533
+ 483945776,
2534
+ 43990325,
2535
+ 106832002,
2536
+ 186451547,
2537
+ 266083308,
2538
+ 932423249,
2539
+ 861060070,
2540
+ 1041341759,
2541
+ 986742920,
2542
+ 613929101,
2543
+ 542559546,
2544
+ 756411363,
2545
+ 701822548,
2546
+ 3316196985,
2547
+ 3244833742,
2548
+ 3425377559,
2549
+ 3370778784,
2550
+ 3601682597,
2551
+ 3530312978,
2552
+ 3744426955,
2553
+ 3689838204,
2554
+ 3819031489,
2555
+ 3881883254,
2556
+ 3928223919,
2557
+ 4007849240,
2558
+ 4037393693,
2559
+ 4100235434,
2560
+ 4180117107,
2561
+ 4259748804,
2562
+ 2310601993,
2563
+ 2373574846,
2564
+ 2151335527,
2565
+ 2231098320,
2566
+ 2596047829,
2567
+ 2659030626,
2568
+ 2470359227,
2569
+ 2550115596,
2570
+ 2947551409,
2571
+ 2876312838,
2572
+ 2788305887,
2573
+ 2733848168,
2574
+ 3165939309,
2575
+ 3094707162,
2576
+ 3040238851,
2577
+ 2985771188
2578
+ ];
2579
+ let crc = seed || 0;
2580
+ for (let i = 0; i < buf.length; i++) {
2581
+ crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf.readUInt8(i)) >>> 0]) >>> 0;
2582
+ }
2583
+ return crc;
2584
+ }
2585
+ static parse(txt) {
2586
+ const fidType = txt[0];
2587
+ const handler = this.FidHandlerTable[fidType];
2588
+ if (handler === void 0) {
2589
+ return {
2590
+ decoded: false,
2591
+ error: "Unsupported FID type: " + fidType
2592
+ };
2593
+ }
2594
+ return handler(txt.substring(1));
2595
+ }
2596
+ static corePduDataHandler(version, minHdrSize, crcLen, hdr, body) {
2597
+ if (hdr.length < minHdrSize) {
2598
+ return {
2599
+ decoded: false,
2600
+ error: "v" + version + " header size too short; expected >= " + minHdrSize + ", got " + hdr.length
2601
+ };
2602
+ }
2603
+ let pduSize = void 0;
2604
+ let pduCompression = 0;
2605
+ let pduEncoding = 0;
2606
+ let pduAppType = 0;
2607
+ let pduAppId = "";
2608
+ let pduCrc = 0;
2609
+ let pduData = void 0;
2610
+ let pduCrcIsOk = false;
2611
+ let pduIsComplete = true;
2612
+ let pduErrors = [];
2613
+ let tail = void 0;
2614
+ let msgNum = 0;
2615
+ let ackOptions = 0;
2616
+ if (version === 1) {
2617
+ pduSize = hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
2618
+ const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
2619
+ if (pduSize > msgSize) {
2620
+ pduIsComplete = false;
2621
+ pduErrors.push("v1 PDU truncated: expecting " + pduSize + ", got " + msgSize);
2622
+ }
2623
+ hdr = hdr.subarray(4);
2624
+ tail = hdr.subarray(0, 7).toString("ascii");
2625
+ hdr = hdr.subarray(7);
2626
+ } else if (version === 2) {
2627
+ hdr = hdr.subarray(1);
2628
+ }
2629
+ msgNum = hdr.readUInt8(0) >> 1 & 127;
2630
+ ackOptions = hdr.readUInt8(0) & 1;
2631
+ hdr = hdr.subarray(1);
2632
+ pduCompression = (hdr.readUInt8(0) << 2 | hdr.readUInt8(1) >> 6 & 3) & 7;
2633
+ pduEncoding = hdr.readUInt8(1) >> 4 & 3;
2634
+ pduAppType = hdr.readUInt8(1) & 15;
2635
+ hdr = hdr.subarray(2);
2636
+ let appIdLen = this.AppTypeToAppIdLenTable[version][pduAppType];
2637
+ if (appIdLen === void 0) {
2638
+ if (version === 2 && (pduAppType & 8) !== 0 && pduAppType !== 13) {
2639
+ appIdLen = (pduAppType & 7) + 1;
2640
+ } else {
2641
+ return {
2642
+ decoded: false,
2643
+ error: "Invalid v" + version + " appType: " + pduAppType
2644
+ };
2645
+ }
2646
+ }
2647
+ const pduIsACARS = [
2648
+ 0 /* ACARS2Char */,
2649
+ 1 /* ACARS4Char */,
2650
+ 2 /* ACARS6Char */,
2651
+ 0 /* ACARS2Char */,
2652
+ 1 /* ACARS4Char */,
2653
+ 2 /* ACARS6Char */
2654
+ ].indexOf(pduAppType) >= 0;
2655
+ if (hdr.length < appIdLen + crcLen) {
2656
+ return {
2657
+ decoded: false,
2658
+ error: "Header too short for v" + version + " appType: " + pduAppType
2659
+ };
2660
+ }
2661
+ pduAppId = hdr.subarray(0, appIdLen).toString("ascii");
2662
+ hdr = hdr.subarray(appIdLen);
2663
+ if (crcLen === 4) {
2664
+ pduCrc = hdr.readUInt8(0) << 24 | hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
2665
+ } else if (crcLen === 2) {
2666
+ pduCrc = hdr.readUInt8(0) << 8 | hdr.readUInt8(1);
2667
+ }
2668
+ hdr = hdr.subarray(crcLen);
2669
+ if (body !== void 0 && body.length > 0) {
2670
+ if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
2671
+ try {
2672
+ pduData = Zlib.inflateRawSync(body, { windowBits: 15 });
2673
+ } catch (e) {
2674
+ pduErrors.push("Inflation failed for body: " + e);
2675
+ }
2676
+ } else if ([0 /* None */, 0 /* None */].indexOf(pduCompression) >= 0) {
2677
+ pduData = body;
2678
+ } else {
2679
+ pduErrors.push("Unsupported v" + version + " compression type: " + pduCompression);
2680
+ }
2681
+ if (pduData !== void 0) {
2682
+ const crcAlgoHandlerByVersion = {
2683
+ 1: (buf, seed) => {
2684
+ return ~this.arinc665Crc32(buf, seed);
2685
+ },
2686
+ 2: this.arincCrc16
2687
+ };
2688
+ const crcAlgoHandler = crcAlgoHandlerByVersion[version];
2689
+ if (crcAlgoHandler === void 0) {
2690
+ return {
2691
+ decoded: false,
2692
+ errors: "No CRC handler for v" + version
2693
+ };
2694
+ }
2695
+ const crcCheck = crcAlgoHandler(pduData, 4294967295);
2696
+ if (crcCheck === pduCrc) {
2697
+ pduCrcIsOk = true;
2698
+ } else {
2699
+ pduErrors.push("Body failed CRC check: provided=" + pduCrc + ", generated=" + crcCheck);
2700
+ }
2701
+ }
2702
+ } else {
2703
+ pduCrcIsOk = true;
2704
+ }
2705
+ let pdu = {
2706
+ version,
2707
+ crc: pduCrc,
2708
+ crcOk: pduCrcIsOk,
2709
+ complete: pduIsComplete,
2710
+ compression: pduCompression,
2711
+ encoding: pduEncoding,
2712
+ msgNum,
2713
+ ackOptions
2714
+ };
2715
+ if (pduIsACARS) {
2716
+ const label = pduAppId.substring(0, 2);
2717
+ const sublabel = appIdLen >= 4 ? pduAppId.substring(2, 4) : void 0;
2718
+ const mfi = appIdLen >= 6 ? pduAppId.substring(4, 6) : void 0;
2719
+ pdu.acars = {
2720
+ ...tail ? { tail } : {},
2721
+ label,
2722
+ ...sublabel ? { sublabel } : {},
2723
+ ...mfi ? { mfi } : {},
2724
+ ...pduData ? { text: pduData.toString("ascii") } : {}
2725
+ };
2726
+ } else {
2727
+ pdu.non_acars = {
2728
+ appId: pduAppId,
2729
+ ...pduData ? { text: pduData.toString("ascii") } : {}
2730
+ };
2731
+ }
2732
+ return {
2733
+ decoded: true,
2734
+ message: {
2735
+ data: pdu
2736
+ }
2737
+ };
2738
+ }
2739
+ static VersionPduHandlerTable = {
2740
+ 1: {
2741
+ [0 /* Data */]: (hdr, body) => {
2742
+ return this.corePduDataHandler(1, 20, MIAMCoreV1CRCLength, hdr, body);
2743
+ },
2744
+ [1 /* Ack */]: void 0,
2745
+ [2 /* Aloha */]: void 0,
2746
+ [3 /* AlohaReply */]: void 0
2747
+ },
2748
+ 2: {
2749
+ [0 /* Data */]: (hdr, body) => {
2750
+ return this.corePduDataHandler(2, 7, MIAMCoreV2CRCLength, hdr, body);
2751
+ },
2752
+ [1 /* Ack */]: void 0,
2753
+ [2 /* Aloha */]: void 0,
2754
+ [3 /* AlohaReply */]: void 0
2755
+ }
2756
+ };
2757
+ };
2758
+
2759
+ // lib/MessageDecoder.ts
2760
+ var MessageDecoder = class {
2761
+ name;
2762
+ plugins;
2763
+ debug;
2764
+ constructor() {
2765
+ this.name = "acars-decoder-typescript";
2766
+ this.plugins = [];
2767
+ this.debug = false;
2768
+ this.registerPlugin(new Label_ColonComma(this));
2769
+ this.registerPlugin(new Label_5Z(this));
2770
+ this.registerPlugin(new Label_12_N_Space(this));
2771
+ this.registerPlugin(new Label_15(this));
2772
+ this.registerPlugin(new Label_15_FST(this));
2773
+ this.registerPlugin(new Label_16_N_Space(this));
2774
+ this.registerPlugin(new Label_20_POS(this));
2775
+ this.registerPlugin(new Label_30_Slash_EA(this));
2776
+ this.registerPlugin(new Label_44_ETA(this));
2777
+ this.registerPlugin(new Label_44_IN(this));
2778
+ this.registerPlugin(new Label_44_OFF(this));
2779
+ this.registerPlugin(new Label_44_ON(this));
2780
+ this.registerPlugin(new Label_44_POS(this));
2781
+ this.registerPlugin(new Label_B6_Forwardslash(this));
2782
+ this.registerPlugin(new Label_H1_FPN(this));
2783
+ this.registerPlugin(new Label_H1_POS(this));
2784
+ this.registerPlugin(new Label_80(this));
2785
+ this.registerPlugin(new Label_8E(this));
2786
+ this.registerPlugin(new Label_1M_Slash(this));
2787
+ this.registerPlugin(new Label_SQ(this));
2788
+ this.registerPlugin(new Label_QP(this));
2789
+ this.registerPlugin(new Label_QQ(this));
2790
+ this.registerPlugin(new Label_QR(this));
2791
+ this.registerPlugin(new Label_QS(this));
2792
+ }
2793
+ registerPlugin(plugin) {
2794
+ const pluginInstance = plugin;
2795
+ this.plugins.push(plugin);
2796
+ return true;
2797
+ }
2798
+ decode(message, options = {}) {
2799
+ if (message.label === "MA") {
2800
+ const decodeResult = MIAMCoreUtils.parse(message.text);
2801
+ if (decodeResult.decoded && decodeResult.message.data !== void 0 && decodeResult.message.data.crcOk && decodeResult.message.data.complete && decodeResult.message.data.acars !== void 0) {
2802
+ message = {
2803
+ ...message,
2804
+ label: decodeResult.message.data.acars.label,
2805
+ ...decodeResult.message.data.acars.sublabel ? { sublabel: decodeResult.message.data.acars.sublabel } : {},
2806
+ ...decodeResult.message.data.acars.mfi ? { mfi: decodeResult.message.data.acars.mfi } : {},
2807
+ ...decodeResult.message.data.acars.text ? { text: decodeResult.message.data.acars.text } : {}
2808
+ };
2809
+ }
2810
+ }
2811
+ const usablePlugins = this.plugins.filter((plugin) => {
2812
+ const qualifiers = plugin.qualifiers();
2813
+ if (qualifiers.labels.includes(message.label)) {
2814
+ if (qualifiers.preambles && qualifiers.preambles.length > 0) {
2815
+ const matching = qualifiers.preambles.filter((preamble) => {
2816
+ return message.text.substring(0, preamble.length) === preamble;
2817
+ });
2818
+ return matching.length >= 1;
2819
+ } else {
2820
+ return true;
2821
+ }
2822
+ }
2823
+ return false;
2824
+ });
2825
+ if (options.debug) {
2826
+ console.log("Usable plugins");
2827
+ console.log(usablePlugins);
2828
+ }
2829
+ let result;
2830
+ if (usablePlugins.length > 0) {
2831
+ const plugin = usablePlugins[0];
2832
+ result = plugin.decode(message);
2833
+ } else {
2834
+ result = {
2835
+ decoded: false,
2836
+ error: "No known decoder plugin for this message",
2837
+ decoder: {
2838
+ name: "none",
2839
+ type: "none",
2840
+ decodeLevel: "none"
2841
+ },
2842
+ message,
2843
+ remaining: {
2844
+ text: message.text
2845
+ },
2846
+ raw: {},
2847
+ formatted: {
2848
+ description: "Not Decoded",
2849
+ items: []
2850
+ }
2851
+ };
2852
+ }
2853
+ if (options.debug) {
2854
+ console.log("Result");
2855
+ console.log(result);
2856
+ }
2857
+ return result;
2858
+ }
2859
+ lookupAirportByIata(iata) {
2860
+ const airportsArray = [];
2861
+ const airport = airportsArray.filter((e) => e.iata === iata);
2862
+ return airport;
2863
+ }
2864
+ };
2865
+ // Annotate the CommonJS export names for ESM import in node:
2866
+ 0 && (module.exports = {
2867
+ IcaoDecoder,
2868
+ MessageDecoder
2869
+ });
2870
+ //# sourceMappingURL=index.js.map