@airframes/acars-decoder 1.6.9 → 1.6.10
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 +644 -451
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +644 -451
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -60,6 +60,192 @@ var DecoderPlugin = class {
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
// lib/utils/coordinate_utils.ts
|
|
64
|
+
var CoordinateUtils = class {
|
|
65
|
+
/**
|
|
66
|
+
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
67
|
+
* @param stringCoords - The string of coordinates to decode
|
|
68
|
+
*
|
|
69
|
+
* @returns An object with latitude and longitude properties
|
|
70
|
+
*/
|
|
71
|
+
static decodeStringCoordinates(stringCoords) {
|
|
72
|
+
var results = {};
|
|
73
|
+
const firstChar = stringCoords.substring(0, 1);
|
|
74
|
+
let middleChar = stringCoords.substring(6, 7);
|
|
75
|
+
let longitudeChars = stringCoords.substring(7, 13);
|
|
76
|
+
if (middleChar == " ") {
|
|
77
|
+
middleChar = stringCoords.substring(7, 8);
|
|
78
|
+
longitudeChars = stringCoords.substring(8, 14);
|
|
79
|
+
}
|
|
80
|
+
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
81
|
+
results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar === "S" ? -1 : 1);
|
|
82
|
+
results.longitude = Number(longitudeChars) / 1e3 * (middleChar === "W" ? -1 : 1);
|
|
83
|
+
} else {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
return results;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
|
|
90
|
+
* @param stringCoords - The string of coordinates to decode
|
|
91
|
+
*
|
|
92
|
+
* @returns An object with latitude and longitude properties
|
|
93
|
+
*/
|
|
94
|
+
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
95
|
+
var results = {};
|
|
96
|
+
const firstChar = stringCoords.substring(0, 1);
|
|
97
|
+
let middleChar = stringCoords.substring(6, 7);
|
|
98
|
+
let longitudeChars = stringCoords.substring(7, 13);
|
|
99
|
+
if (middleChar == " ") {
|
|
100
|
+
middleChar = stringCoords.substring(7, 8);
|
|
101
|
+
longitudeChars = stringCoords.substring(8, 14);
|
|
102
|
+
}
|
|
103
|
+
const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
|
|
104
|
+
const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
|
|
105
|
+
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
106
|
+
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
107
|
+
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
108
|
+
results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
|
|
109
|
+
results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
|
|
110
|
+
} else {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
return results;
|
|
114
|
+
}
|
|
115
|
+
static coordinateString(coords) {
|
|
116
|
+
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
117
|
+
const lonDir = coords.longitude > 0 ? "E" : "W";
|
|
118
|
+
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// lib/utils/result_formatter.ts
|
|
123
|
+
var ResultFormatter = class {
|
|
124
|
+
static position(decodeResult, value) {
|
|
125
|
+
decodeResult.raw.position = value;
|
|
126
|
+
decodeResult.formatted.items.push({
|
|
127
|
+
type: "aircraft_position",
|
|
128
|
+
code: "POS",
|
|
129
|
+
label: "Aircraft Position",
|
|
130
|
+
value: CoordinateUtils.coordinateString(value)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
static altitude(decodeResult, value) {
|
|
134
|
+
decodeResult.raw.altitude = value;
|
|
135
|
+
decodeResult.formatted.items.push({
|
|
136
|
+
type: "altitude",
|
|
137
|
+
code: "ALT",
|
|
138
|
+
label: "Altitude",
|
|
139
|
+
value: `${decodeResult.raw.altitude} feet`
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
static flightNumber(decodeResult, value) {
|
|
143
|
+
decodeResult.raw.flight_number = value;
|
|
144
|
+
}
|
|
145
|
+
static departureAirport(decodeResult, value) {
|
|
146
|
+
decodeResult.raw.departure_icao = value;
|
|
147
|
+
decodeResult.formatted.items.push({
|
|
148
|
+
type: "origin",
|
|
149
|
+
code: "ORG",
|
|
150
|
+
label: "Origin",
|
|
151
|
+
value: decodeResult.raw.departure_icao
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
static departureRunway(decodeResult, value) {
|
|
155
|
+
decodeResult.raw.departure_runway = value;
|
|
156
|
+
decodeResult.formatted.items.push({
|
|
157
|
+
type: "runway",
|
|
158
|
+
code: "DEPRWY",
|
|
159
|
+
label: "Departure Runway",
|
|
160
|
+
value: decodeResult.raw.departure_runway
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
static arrivalAirport(decodeResult, value) {
|
|
164
|
+
decodeResult.raw.arrival_icao = value;
|
|
165
|
+
decodeResult.formatted.items.push({
|
|
166
|
+
type: "destination",
|
|
167
|
+
code: "DST",
|
|
168
|
+
label: "Destination",
|
|
169
|
+
value: decodeResult.raw.arrival_icao
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
static eta(decodeResult, value) {
|
|
173
|
+
decodeResult.raw.eta_time = value;
|
|
174
|
+
decodeResult.formatted.items.push({
|
|
175
|
+
type: "eta",
|
|
176
|
+
code: "ETA",
|
|
177
|
+
label: "Estimated Time of Arrival",
|
|
178
|
+
value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
static arrivalRunway(decodeResult, value) {
|
|
182
|
+
decodeResult.raw.arrival_runway = value;
|
|
183
|
+
decodeResult.formatted.items.push({
|
|
184
|
+
type: "runway",
|
|
185
|
+
code: "ARWY",
|
|
186
|
+
label: "Arrival Runway",
|
|
187
|
+
value: decodeResult.raw.arrival_runway
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
static currentFuel(decodeResult, value) {
|
|
191
|
+
decodeResult.raw.fuel_on_board = value;
|
|
192
|
+
decodeResult.formatted.items.push({
|
|
193
|
+
type: "fuel_on_board",
|
|
194
|
+
code: "FOB",
|
|
195
|
+
label: "Fuel On Board",
|
|
196
|
+
value: decodeResult.raw.fuel_on_board.toString()
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
static remainingFuel(decodeResult, value) {
|
|
200
|
+
decodeResult.raw.fuel_remaining = value;
|
|
201
|
+
decodeResult.formatted.items.push({
|
|
202
|
+
type: "fuel_remaining",
|
|
203
|
+
code: "FUEL",
|
|
204
|
+
label: "Fuel Remaining",
|
|
205
|
+
value: decodeResult.raw.fuel_remaining.toString()
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
static checksum(decodeResult, value) {
|
|
209
|
+
decodeResult.raw.checksum = Number("0x" + value);
|
|
210
|
+
decodeResult.formatted.items.push({
|
|
211
|
+
type: "message_checksum",
|
|
212
|
+
code: "CHECKSUM",
|
|
213
|
+
label: "Message Checksum",
|
|
214
|
+
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
static groundspeed(decodeResult, value) {
|
|
218
|
+
decodeResult.raw.groundspeed = value;
|
|
219
|
+
decodeResult.formatted.items.push({
|
|
220
|
+
type: "aircraft_groundspeed",
|
|
221
|
+
code: "GSPD",
|
|
222
|
+
label: "Aircraft Groundspeed",
|
|
223
|
+
value: `${decodeResult.raw.groundspeed}`
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
static temperature(decodeResult, value) {
|
|
227
|
+
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
228
|
+
decodeResult.formatted.items.push({
|
|
229
|
+
type: "outside_air_temperature",
|
|
230
|
+
code: "OATEMP",
|
|
231
|
+
label: "Outside Air Temperature (C)",
|
|
232
|
+
value: `${decodeResult.raw.outside_air_temperature}`
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
static heading(decodeResult, value) {
|
|
236
|
+
decodeResult.raw.heading = value;
|
|
237
|
+
decodeResult.formatted.items.push({
|
|
238
|
+
type: "heading",
|
|
239
|
+
code: "HDG",
|
|
240
|
+
label: "Heading",
|
|
241
|
+
value: `${decodeResult.raw.heading}`
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
static unknown(decodeResult, value) {
|
|
245
|
+
decodeResult.remaining.text += "," + value;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
63
249
|
// lib/plugins/Label_5Z.ts
|
|
64
250
|
var Label_5Z = class extends DecoderPlugin {
|
|
65
251
|
name = "label-5z";
|
|
@@ -90,141 +276,327 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
90
276
|
};
|
|
91
277
|
qualifiers() {
|
|
92
278
|
return {
|
|
93
|
-
labels: ["5Z"]
|
|
279
|
+
labels: ["5Z"]
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
decode(message, options = {}) {
|
|
283
|
+
const decodeResult = this.defaultResult();
|
|
284
|
+
decodeResult.decoder.name = this.name;
|
|
285
|
+
decodeResult.formatted.description = "Airline Designated Downlink";
|
|
286
|
+
const uaRegex = /^\/(?<type>\w+) (?<remainder>.+)/;
|
|
287
|
+
let results = message.text.match(uaRegex);
|
|
288
|
+
if (results && results.length >= 2) {
|
|
289
|
+
const type = results.groups.type.split("/")[0];
|
|
290
|
+
const { remainder } = results.groups;
|
|
291
|
+
const typeDescription = this.descriptions[type] ? this.descriptions[type] : "Unknown";
|
|
292
|
+
decodeResult.raw.airline = "United Airlines";
|
|
293
|
+
decodeResult.formatted.items.push({
|
|
294
|
+
type: "airline",
|
|
295
|
+
label: "Airline",
|
|
296
|
+
value: "United Airlines"
|
|
297
|
+
});
|
|
298
|
+
decodeResult.raw.message_type = type;
|
|
299
|
+
decodeResult.formatted.items.push({
|
|
300
|
+
type: "message_type",
|
|
301
|
+
label: "Message Type",
|
|
302
|
+
value: `${typeDescription} (${type})`
|
|
303
|
+
});
|
|
304
|
+
if (type === "B3") {
|
|
305
|
+
const rdcRegex = /^(?<from>\w\w\w)(?<to>\w\w\w) (?<unknown1>\d\d) R(?<runway>.+) G(?<unknown2>.+)$/;
|
|
306
|
+
results = remainder.match(rdcRegex);
|
|
307
|
+
if (results) {
|
|
308
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.from);
|
|
309
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.to);
|
|
310
|
+
ResultFormatter.arrivalRunway(decodeResult, results.groups.runway);
|
|
311
|
+
} else {
|
|
312
|
+
if (options.debug) {
|
|
313
|
+
console.log(`Decoder: Unkown 5Z RDC format: ${remainder}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
decodeResult.remaining.text = remainder;
|
|
318
|
+
}
|
|
319
|
+
decodeResult.decoded = true;
|
|
320
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
321
|
+
} else {
|
|
322
|
+
if (options.debug) {
|
|
323
|
+
console.log(`Decoder: Unknown 5Z message: ${message.text}`);
|
|
324
|
+
}
|
|
325
|
+
decodeResult.remaining.text = message.text;
|
|
326
|
+
decodeResult.decoded = false;
|
|
327
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
328
|
+
}
|
|
329
|
+
return decodeResult;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// lib/plugins/Label_10_LDR.ts
|
|
334
|
+
var Label_10_LDR = class extends DecoderPlugin {
|
|
335
|
+
// eslint-disable-line camelcase
|
|
336
|
+
name = "label-10-ldr";
|
|
337
|
+
qualifiers() {
|
|
338
|
+
return {
|
|
339
|
+
labels: ["10"],
|
|
340
|
+
preambles: ["LDR"]
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
decode(message, options = {}) {
|
|
344
|
+
const decodeResult = this.defaultResult();
|
|
345
|
+
decodeResult.decoder.name = this.name;
|
|
346
|
+
decodeResult.formatted.description = "Position Report";
|
|
347
|
+
decodeResult.message = message;
|
|
348
|
+
const parts = message.text.split(",");
|
|
349
|
+
if (parts.length < 17) {
|
|
350
|
+
if (options?.debug) {
|
|
351
|
+
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
352
|
+
}
|
|
353
|
+
decodeResult.remaining.text = message.text;
|
|
354
|
+
decodeResult.decoded = false;
|
|
355
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
356
|
+
return decodeResult;
|
|
357
|
+
}
|
|
358
|
+
const lat = parts[5];
|
|
359
|
+
const lon = parts[6];
|
|
360
|
+
const position = {
|
|
361
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1).trim()),
|
|
362
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim())
|
|
363
|
+
};
|
|
364
|
+
ResultFormatter.position(decodeResult, position);
|
|
365
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
366
|
+
ResultFormatter.departureAirport(decodeResult, parts[9]);
|
|
367
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[10]);
|
|
368
|
+
ResultFormatter.arrivalRunway(decodeResult, parts[12].split("/")[0]);
|
|
369
|
+
decodeResult.remaining.text = [...parts.slice(0, 5), parts[11], ...parts.slice(13)].join(",");
|
|
370
|
+
decodeResult.decoded = true;
|
|
371
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
372
|
+
return decodeResult;
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// lib/plugins/Label_10_POS.ts
|
|
377
|
+
var Label_10_POS = class extends DecoderPlugin {
|
|
378
|
+
// eslint-disable-line camelcase
|
|
379
|
+
name = "label-10-pos";
|
|
380
|
+
qualifiers() {
|
|
381
|
+
return {
|
|
382
|
+
labels: ["10"],
|
|
383
|
+
preambles: ["POS"]
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
decode(message, options = {}) {
|
|
387
|
+
const decodeResult = this.defaultResult();
|
|
388
|
+
decodeResult.decoder.name = this.name;
|
|
389
|
+
decodeResult.formatted.description = "Position Report";
|
|
390
|
+
decodeResult.message = message;
|
|
391
|
+
const parts = message.text.split(",");
|
|
392
|
+
if (parts.length !== 12) {
|
|
393
|
+
if (options?.debug) {
|
|
394
|
+
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
395
|
+
}
|
|
396
|
+
decodeResult.remaining.text = message.text;
|
|
397
|
+
decodeResult.decoded = false;
|
|
398
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
399
|
+
return decodeResult;
|
|
400
|
+
}
|
|
401
|
+
const lat = parts[1].trim();
|
|
402
|
+
const lon = parts[2].trim();
|
|
403
|
+
const position = {
|
|
404
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1).trim()) / 100,
|
|
405
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim()) / 100
|
|
406
|
+
};
|
|
407
|
+
ResultFormatter.position(decodeResult, position);
|
|
408
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
409
|
+
decodeResult.remaining.text = [parts[0], ...parts.slice(3, 7), ...parts.slice(8)].join(",");
|
|
410
|
+
decodeResult.decoded = true;
|
|
411
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
412
|
+
return decodeResult;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
// lib/DateTimeUtils.ts
|
|
417
|
+
var DateTimeUtils = class {
|
|
418
|
+
// Expects a four digit UTC time string (HHMM)
|
|
419
|
+
static UTCToString(UTCString) {
|
|
420
|
+
let utcDate = /* @__PURE__ */ new Date();
|
|
421
|
+
utcDate.setUTCHours(+UTCString.substr(0, 2), +UTCString.substr(2, 2), 0);
|
|
422
|
+
return utcDate.toTimeString();
|
|
423
|
+
}
|
|
424
|
+
// Expects a six digit date string and a four digit UTC time string
|
|
425
|
+
// (DDMMYY) (HHMM)
|
|
426
|
+
static UTCDateTimeToString(dateString, timeString) {
|
|
427
|
+
let utcDate = /* @__PURE__ */ new Date();
|
|
428
|
+
utcDate.setUTCDate(+dateString.substr(0, 2));
|
|
429
|
+
utcDate.setUTCMonth(+dateString.substr(2, 2));
|
|
430
|
+
if (dateString.length === 6) {
|
|
431
|
+
utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
|
|
432
|
+
}
|
|
433
|
+
if (timeString.length === 6) {
|
|
434
|
+
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), +timeString.substr(4, 2));
|
|
435
|
+
} else {
|
|
436
|
+
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), 0);
|
|
437
|
+
}
|
|
438
|
+
return utcDate.toUTCString();
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
*
|
|
442
|
+
* @param time HHMMSS
|
|
443
|
+
* @returns seconds since midnight
|
|
444
|
+
*/
|
|
445
|
+
static convertHHMMSSToTod(time) {
|
|
446
|
+
const h = Number(time.substring(0, 2));
|
|
447
|
+
const m = Number(time.substring(2, 4));
|
|
448
|
+
const s = Number(time.substring(4, 6));
|
|
449
|
+
const tod = h * 3600 + m * 60 + s;
|
|
450
|
+
return tod;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
*
|
|
454
|
+
* @param time HHMMSS
|
|
455
|
+
* @param date MMDDYY or MMDDYYYY
|
|
456
|
+
* @returns seconds since epoch
|
|
457
|
+
*/
|
|
458
|
+
static convertDateTimeToEpoch(time, date) {
|
|
459
|
+
if (date.length === 6) {
|
|
460
|
+
date = date.substring(0, 4) + `20${date.substring(4, 6)}`;
|
|
461
|
+
}
|
|
462
|
+
const timestamp = `${date.substring(4, 8)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
|
|
463
|
+
const millis = Date.parse(timestamp);
|
|
464
|
+
return millis / 1e3;
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// lib/utils/route_utils.ts
|
|
469
|
+
var RouteUtils = class _RouteUtils {
|
|
470
|
+
static routeToString(route) {
|
|
471
|
+
let str = "";
|
|
472
|
+
if (route.name) {
|
|
473
|
+
str += route.name;
|
|
474
|
+
}
|
|
475
|
+
if (route.runway) {
|
|
476
|
+
str += `(${route.runway})`;
|
|
477
|
+
}
|
|
478
|
+
if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
|
|
479
|
+
str += " starting at ";
|
|
480
|
+
} else if (str.length !== 0 && route.waypoints) {
|
|
481
|
+
str += ": ";
|
|
482
|
+
}
|
|
483
|
+
if (route.waypoints) {
|
|
484
|
+
str += _RouteUtils.waypointsToString(route.waypoints);
|
|
485
|
+
}
|
|
486
|
+
return str;
|
|
487
|
+
}
|
|
488
|
+
static waypointToString(waypoint) {
|
|
489
|
+
let s = waypoint.name;
|
|
490
|
+
if (waypoint.latitude && waypoint.longitude) {
|
|
491
|
+
s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
|
|
492
|
+
}
|
|
493
|
+
if (waypoint.offset) {
|
|
494
|
+
s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
|
|
495
|
+
}
|
|
496
|
+
if (waypoint.time && waypoint.timeFormat) {
|
|
497
|
+
s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
|
|
498
|
+
}
|
|
499
|
+
return s;
|
|
500
|
+
}
|
|
501
|
+
static getWaypoint(leg) {
|
|
502
|
+
const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
|
|
503
|
+
if (regex?.length == 4) {
|
|
504
|
+
return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
|
|
505
|
+
}
|
|
506
|
+
const waypoint = leg.split(",");
|
|
507
|
+
if (waypoint.length == 2) {
|
|
508
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
509
|
+
if (position) {
|
|
510
|
+
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (leg.length == 13 || leg.length == 14) {
|
|
514
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
515
|
+
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
516
|
+
if (position) {
|
|
517
|
+
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return { name: leg };
|
|
521
|
+
}
|
|
522
|
+
// move out if we want public
|
|
523
|
+
static timestampToString(time, format) {
|
|
524
|
+
const date = new Date(time * 1e3);
|
|
525
|
+
if (format == "tod") {
|
|
526
|
+
return date.toISOString().slice(11, 19);
|
|
527
|
+
}
|
|
528
|
+
return date.toISOString().slice(0, -5) + "Z";
|
|
529
|
+
}
|
|
530
|
+
static waypointsToString(waypoints) {
|
|
531
|
+
let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
|
|
532
|
+
if (str.startsWith(" > ")) {
|
|
533
|
+
str = ">>" + str.slice(2);
|
|
534
|
+
}
|
|
535
|
+
return str;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// lib/plugins/Label_10_Slash.ts
|
|
540
|
+
var Label_10_Slash = class extends DecoderPlugin {
|
|
541
|
+
// eslint-disable-line camelcase
|
|
542
|
+
name = "label-10-slash";
|
|
543
|
+
qualifiers() {
|
|
544
|
+
return {
|
|
545
|
+
labels: ["10"],
|
|
546
|
+
preambles: ["/"]
|
|
94
547
|
};
|
|
95
548
|
}
|
|
96
549
|
decode(message, options = {}) {
|
|
97
550
|
const decodeResult = this.defaultResult();
|
|
98
551
|
decodeResult.decoder.name = this.name;
|
|
99
|
-
decodeResult.formatted.description = "
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const typeDescription = this.descriptions[type] ? this.descriptions[type] : "Unknown";
|
|
106
|
-
decodeResult.raw.airline = "United Airlines";
|
|
107
|
-
decodeResult.formatted.items.push({
|
|
108
|
-
type: "airline",
|
|
109
|
-
label: "Airline",
|
|
110
|
-
value: "United Airlines"
|
|
111
|
-
});
|
|
112
|
-
decodeResult.raw.message_type = type;
|
|
113
|
-
decodeResult.formatted.items.push({
|
|
114
|
-
type: "message_type",
|
|
115
|
-
label: "Message Type",
|
|
116
|
-
value: `${typeDescription} (${type})`
|
|
117
|
-
});
|
|
118
|
-
if (type === "B3") {
|
|
119
|
-
const rdcRegex = /^(?<from>\w\w\w)(?<to>\w\w\w) (?<unknown1>\d\d) R(?<runway>.+) G(?<unknown2>.+)$/;
|
|
120
|
-
results = remainder.match(rdcRegex);
|
|
121
|
-
if (results) {
|
|
122
|
-
decodeResult.raw.origin = results.groups.from;
|
|
123
|
-
decodeResult.formatted.items.push({
|
|
124
|
-
type: "origin",
|
|
125
|
-
label: "Origin",
|
|
126
|
-
value: `${results.groups.from}`
|
|
127
|
-
});
|
|
128
|
-
decodeResult.raw.destination = results.groups.to;
|
|
129
|
-
decodeResult.formatted.items.push({
|
|
130
|
-
type: "destination",
|
|
131
|
-
label: "Destination",
|
|
132
|
-
value: `${results.groups.to}`
|
|
133
|
-
});
|
|
134
|
-
decodeResult.formatted.items.push({
|
|
135
|
-
type: "unknown1",
|
|
136
|
-
label: "Unknown Field 1",
|
|
137
|
-
value: `${results.groups.unknown1}`
|
|
138
|
-
});
|
|
139
|
-
decodeResult.raw.runway = results.groups.runway;
|
|
140
|
-
decodeResult.formatted.items.push({
|
|
141
|
-
type: "runway",
|
|
142
|
-
label: "Runway",
|
|
143
|
-
value: `${results.groups.runway}`
|
|
144
|
-
});
|
|
145
|
-
decodeResult.formatted.items.push({
|
|
146
|
-
type: "unknown2",
|
|
147
|
-
label: "Unknown Field 2",
|
|
148
|
-
value: `${results.groups.unknown2}`
|
|
149
|
-
});
|
|
150
|
-
} else {
|
|
151
|
-
if (options.debug) {
|
|
152
|
-
console.log(`Decoder: Unkown 5Z RDC format: ${remainder}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
} else {
|
|
156
|
-
decodeResult.remaining.text = remainder;
|
|
157
|
-
}
|
|
158
|
-
decodeResult.decoded = true;
|
|
159
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
160
|
-
} else {
|
|
161
|
-
if (options.debug) {
|
|
162
|
-
console.log(`Decoder: Unknown 5Z message: ${message.text}`);
|
|
552
|
+
decodeResult.formatted.description = "Position Report";
|
|
553
|
+
decodeResult.message = message;
|
|
554
|
+
const parts = message.text.split("/");
|
|
555
|
+
if (parts.length < 17) {
|
|
556
|
+
if (options?.debug) {
|
|
557
|
+
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
163
558
|
}
|
|
164
559
|
decodeResult.remaining.text = message.text;
|
|
165
560
|
decodeResult.decoded = false;
|
|
166
561
|
decodeResult.decoder.decodeLevel = "none";
|
|
562
|
+
return decodeResult;
|
|
167
563
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* @param stringCoords - The string of coordinates to decode
|
|
200
|
-
*
|
|
201
|
-
* @returns An object with latitude and longitude properties
|
|
202
|
-
*/
|
|
203
|
-
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
204
|
-
var results = {};
|
|
205
|
-
const firstChar = stringCoords.substring(0, 1);
|
|
206
|
-
let middleChar = stringCoords.substring(6, 7);
|
|
207
|
-
let longitudeChars = stringCoords.substring(7, 13);
|
|
208
|
-
if (middleChar == " ") {
|
|
209
|
-
middleChar = stringCoords.substring(7, 8);
|
|
210
|
-
longitudeChars = stringCoords.substring(8, 14);
|
|
211
|
-
}
|
|
212
|
-
const latDeg = Math.trunc(Number(stringCoords.substring(1, 6)) / 1e3);
|
|
213
|
-
const latMin = Number(stringCoords.substring(1, 6)) % 1e3 / 10;
|
|
214
|
-
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
215
|
-
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
216
|
-
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
217
|
-
results.latitude = (latDeg + latMin / 60) * (firstChar === "S" ? -1 : 1);
|
|
218
|
-
results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
|
|
219
|
-
} else {
|
|
220
|
-
return;
|
|
564
|
+
const lat = parts[1];
|
|
565
|
+
const lon = parts[2];
|
|
566
|
+
const position = {
|
|
567
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
|
|
568
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
|
|
569
|
+
};
|
|
570
|
+
ResultFormatter.position(decodeResult, position);
|
|
571
|
+
ResultFormatter.heading(decodeResult, Number(parts[5]));
|
|
572
|
+
ResultFormatter.altitude(decodeResult, 100 * Number(parts[6]));
|
|
573
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
574
|
+
ResultFormatter.eta(decodeResult, parts[8] + "00");
|
|
575
|
+
const waypoints = [{
|
|
576
|
+
name: parts[11]
|
|
577
|
+
}, {
|
|
578
|
+
name: parts[12],
|
|
579
|
+
time: DateTimeUtils.convertHHMMSSToTod(parts[13] + "00"),
|
|
580
|
+
timeFormat: "tod"
|
|
581
|
+
}, {
|
|
582
|
+
name: parts[14],
|
|
583
|
+
time: DateTimeUtils.convertHHMMSSToTod(parts[15] + "00"),
|
|
584
|
+
timeFormat: "tod"
|
|
585
|
+
}];
|
|
586
|
+
decodeResult.raw.route = { waypoints };
|
|
587
|
+
decodeResult.formatted.items.push({
|
|
588
|
+
type: "aircraft_route",
|
|
589
|
+
code: "ROUTE",
|
|
590
|
+
label: "Aircraft Route",
|
|
591
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
592
|
+
});
|
|
593
|
+
if (parts[16]) {
|
|
594
|
+
ResultFormatter.departureAirport(decodeResult, parts[16]);
|
|
221
595
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const lonDir = coords.longitude > 0 ? "E" : "W";
|
|
227
|
-
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
596
|
+
decodeResult.remaining.text = [parts[3], parts[4], ...parts.slice(9, 11), ...parts.slice(17)].join("/");
|
|
597
|
+
decodeResult.decoded = true;
|
|
598
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
599
|
+
return decodeResult;
|
|
228
600
|
}
|
|
229
601
|
};
|
|
230
602
|
|
|
@@ -253,19 +625,14 @@ var Label_12_N_Space = class extends DecoderPlugin {
|
|
|
253
625
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
254
626
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
255
627
|
};
|
|
256
|
-
|
|
628
|
+
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
257
629
|
decodeResult.formatted.items.push({
|
|
258
630
|
type: "aircraft_position",
|
|
259
631
|
code: "POS",
|
|
260
632
|
label: "Aircraft Position",
|
|
261
633
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
262
634
|
});
|
|
263
|
-
|
|
264
|
-
type: "flight_level",
|
|
265
|
-
code: "FL",
|
|
266
|
-
label: "Flight Level",
|
|
267
|
-
value: decodeResult.raw.flight_level
|
|
268
|
-
});
|
|
635
|
+
ResultFormatter.altitude(decodeResult, altitude);
|
|
269
636
|
decodeResult.remaining.text = `,${results.groups.unkwn1} ,${results.groups.unkwn2}, ${results.groups.unkwn3}`;
|
|
270
637
|
decodeResult.decoded = true;
|
|
271
638
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -327,39 +694,35 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
327
694
|
decodeResult.decoder.name = this.name;
|
|
328
695
|
decodeResult.formatted.description = "Position Report";
|
|
329
696
|
decodeResult.message = message;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
697
|
+
const parts = message.text.split(" ");
|
|
698
|
+
const header = parts[0];
|
|
699
|
+
decodeResult.raw.departure_icao = header.substring(5, 9);
|
|
700
|
+
decodeResult.raw.arrival_icao = header.substring(9, 13);
|
|
701
|
+
const stringCoords = header.substring(13);
|
|
333
702
|
const firstChar = stringCoords.substring(0, 1);
|
|
334
703
|
const middleChar = stringCoords.substring(7, 8);
|
|
335
704
|
decodeResult.raw.position = {};
|
|
336
705
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
337
706
|
decodeResult.raw.position.latitude = Number(stringCoords.substring(1, 7)) / 1e4 * (firstChar === "S" ? -1 : 1);
|
|
338
|
-
decodeResult.raw.position.longitude = Number(stringCoords.substring(8,
|
|
707
|
+
decodeResult.raw.position.longitude = Number(stringCoords.substring(8, 15)) / 1e4 * (middleChar === "W" ? -1 : 1);
|
|
708
|
+
decodeResult.raw.altitude = Number(stringCoords.substring(15)) * 100;
|
|
339
709
|
} else {
|
|
340
710
|
decodeResult.decoded = false;
|
|
341
711
|
decodeResult.decoder.decodeLevel = "none";
|
|
342
712
|
return decodeResult;
|
|
343
713
|
}
|
|
344
714
|
decodeResult.formatted.items.push({
|
|
345
|
-
type: "
|
|
346
|
-
|
|
715
|
+
type: "aircraft_position",
|
|
716
|
+
code: "POS",
|
|
717
|
+
label: "Aircraft Position",
|
|
347
718
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
348
719
|
});
|
|
349
|
-
decodeResult.
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
value: decodeResult.raw.departure_icao
|
|
354
|
-
});
|
|
355
|
-
decodeResult.formatted.items.push({
|
|
356
|
-
type: "destination",
|
|
357
|
-
code: "DST",
|
|
358
|
-
label: "Destination",
|
|
359
|
-
value: decodeResult.raw.arrival_icao
|
|
360
|
-
});
|
|
720
|
+
ResultFormatter.altitude(decodeResult, decodeResult.raw.altitude);
|
|
721
|
+
ResultFormatter.departureAirport(decodeResult, decodeResult.raw.departure_icao);
|
|
722
|
+
ResultFormatter.arrivalAirport(decodeResult, decodeResult.raw.arrival_icao);
|
|
723
|
+
decodeResult.remaining.text = parts.slice(1).join(" ");
|
|
361
724
|
decodeResult.decoded = true;
|
|
362
|
-
decodeResult.decoder.decodeLevel = "
|
|
725
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
363
726
|
return decodeResult;
|
|
364
727
|
}
|
|
365
728
|
};
|
|
@@ -390,19 +753,14 @@ var Label_16_N_Space = class extends DecoderPlugin {
|
|
|
390
753
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
391
754
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
392
755
|
};
|
|
393
|
-
|
|
756
|
+
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
394
757
|
decodeResult.formatted.items.push({
|
|
395
758
|
type: "aircraft_position",
|
|
396
759
|
code: "POS",
|
|
397
760
|
label: "Aircraft Position",
|
|
398
761
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
399
762
|
});
|
|
400
|
-
|
|
401
|
-
type: "flight_level",
|
|
402
|
-
code: "FL",
|
|
403
|
-
label: "Flight Level",
|
|
404
|
-
value: decodeResult.raw.flight_level
|
|
405
|
-
});
|
|
763
|
+
ResultFormatter.altitude(decodeResult, altitude);
|
|
406
764
|
decodeResult.remaining.text = `,${results.groups.unkwn1} ,${results.groups.unkwn2}`;
|
|
407
765
|
decodeResult.decoded = true;
|
|
408
766
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -435,58 +793,6 @@ var Label_16_N_Space = class extends DecoderPlugin {
|
|
|
435
793
|
}
|
|
436
794
|
};
|
|
437
795
|
|
|
438
|
-
// lib/DateTimeUtils.ts
|
|
439
|
-
var DateTimeUtils = class {
|
|
440
|
-
// Expects a four digit UTC time string (HHMM)
|
|
441
|
-
static UTCToString(UTCString) {
|
|
442
|
-
let utcDate = /* @__PURE__ */ new Date();
|
|
443
|
-
utcDate.setUTCHours(+UTCString.substr(0, 2), +UTCString.substr(2, 2), 0);
|
|
444
|
-
return utcDate.toTimeString();
|
|
445
|
-
}
|
|
446
|
-
// Expects a six digit date string and a four digit UTC time string
|
|
447
|
-
// (DDMMYY) (HHMM)
|
|
448
|
-
static UTCDateTimeToString(dateString, timeString) {
|
|
449
|
-
let utcDate = /* @__PURE__ */ new Date();
|
|
450
|
-
utcDate.setUTCDate(+dateString.substr(0, 2));
|
|
451
|
-
utcDate.setUTCMonth(+dateString.substr(2, 2));
|
|
452
|
-
if (dateString.length === 6) {
|
|
453
|
-
utcDate.setUTCFullYear(2e3 + +dateString.substr(4, 2));
|
|
454
|
-
}
|
|
455
|
-
if (timeString.length === 6) {
|
|
456
|
-
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), +timeString.substr(4, 2));
|
|
457
|
-
} else {
|
|
458
|
-
utcDate.setUTCHours(+timeString.substr(0, 2), +timeString.substr(2, 2), 0);
|
|
459
|
-
}
|
|
460
|
-
return utcDate.toUTCString();
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
*
|
|
464
|
-
* @param time HHMMSS
|
|
465
|
-
* @returns seconds since midnight
|
|
466
|
-
*/
|
|
467
|
-
static convertHHMMSSToTod(time) {
|
|
468
|
-
const h = Number(time.substring(0, 2));
|
|
469
|
-
const m = Number(time.substring(2, 4));
|
|
470
|
-
const s = Number(time.substring(4, 6));
|
|
471
|
-
const tod = h * 3600 + m * 60 + s;
|
|
472
|
-
return tod;
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
*
|
|
476
|
-
* @param time HHMMSS
|
|
477
|
-
* @param date MMDDYY or MMDDYYYY
|
|
478
|
-
* @returns seconds since epoch
|
|
479
|
-
*/
|
|
480
|
-
static convertDateTimeToEpoch(time, date) {
|
|
481
|
-
if (date.length === 6) {
|
|
482
|
-
date = date.substring(0, 4) + `20${date.substring(4, 6)}`;
|
|
483
|
-
}
|
|
484
|
-
const timestamp = `${date.substring(4, 8)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
|
|
485
|
-
const millis = Date.parse(timestamp);
|
|
486
|
-
return millis / 1e3;
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
|
|
490
796
|
// lib/plugins/Label_1M_Slash.ts
|
|
491
797
|
var Label_1M_Slash = class extends DecoderPlugin {
|
|
492
798
|
name = "label-1m-slash";
|
|
@@ -563,6 +869,7 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
563
869
|
if (decodeResult.raw.position) {
|
|
564
870
|
decodeResult.formatted.items.push({
|
|
565
871
|
type: "position",
|
|
872
|
+
code: "POS",
|
|
566
873
|
label: "Position",
|
|
567
874
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
568
875
|
});
|
|
@@ -576,6 +883,7 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
576
883
|
if (decodeResult.raw.position) {
|
|
577
884
|
decodeResult.formatted.items.push({
|
|
578
885
|
type: "position",
|
|
886
|
+
code: "POS",
|
|
579
887
|
label: "Position",
|
|
580
888
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
581
889
|
});
|
|
@@ -615,7 +923,7 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
615
923
|
processAlt(decodeResult, fields[3]);
|
|
616
924
|
processTemp(decodeResult, fields[6]);
|
|
617
925
|
processArrvApt(decodeResult, fields[8]);
|
|
618
|
-
decodeResult.
|
|
926
|
+
decodeResult.remaining.text = [
|
|
619
927
|
fields[1],
|
|
620
928
|
fields[2],
|
|
621
929
|
fields[4],
|
|
@@ -979,44 +1287,27 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
979
1287
|
console.log(results.groups);
|
|
980
1288
|
}
|
|
981
1289
|
decodeResult.raw.position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords);
|
|
982
|
-
|
|
983
|
-
decodeResult.raw.departure_icao = results.groups.departure_icao;
|
|
984
|
-
decodeResult.raw.arrival_icao = results.groups.arrival_icao;
|
|
1290
|
+
const flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? 0 : Number(results.groups.flight_level_or_ground);
|
|
985
1291
|
decodeResult.raw.current_time = Date.parse(
|
|
986
1292
|
(/* @__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"
|
|
987
1293
|
);
|
|
988
1294
|
decodeResult.raw.eta_time = Date.parse(
|
|
989
|
-
(/* @__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"
|
|
990
|
-
);
|
|
991
|
-
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
992
|
-
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
993
|
-
}
|
|
994
|
-
if (decodeResult.raw.position) {
|
|
995
|
-
decodeResult.formatted.items.push({
|
|
996
|
-
type: "aircraft_position",
|
|
997
|
-
code: "POS",
|
|
998
|
-
label: "Aircraft Position",
|
|
999
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
decodeResult.
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
label: "Origin",
|
|
1006
|
-
value: decodeResult.raw.departure_icao
|
|
1007
|
-
});
|
|
1008
|
-
decodeResult.formatted.items.push({
|
|
1009
|
-
type: "destination",
|
|
1010
|
-
code: "DST",
|
|
1011
|
-
label: "Destination",
|
|
1012
|
-
value: decodeResult.raw.arrival_icao
|
|
1013
|
-
});
|
|
1014
|
-
decodeResult.formatted.items.push({
|
|
1015
|
-
type: "flight_level",
|
|
1016
|
-
code: "FL",
|
|
1017
|
-
label: "Flight Level",
|
|
1018
|
-
value: decodeResult.raw.flight_level
|
|
1019
|
-
});
|
|
1295
|
+
(/* @__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"
|
|
1296
|
+
);
|
|
1297
|
+
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1298
|
+
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1299
|
+
}
|
|
1300
|
+
if (decodeResult.raw.position) {
|
|
1301
|
+
decodeResult.formatted.items.push({
|
|
1302
|
+
type: "aircraft_position",
|
|
1303
|
+
code: "POS",
|
|
1304
|
+
label: "Aircraft Position",
|
|
1305
|
+
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1309
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1310
|
+
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
1020
1311
|
}
|
|
1021
1312
|
decodeResult.decoded = true;
|
|
1022
1313
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1119,13 +1410,9 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
1119
1410
|
break;
|
|
1120
1411
|
}
|
|
1121
1412
|
case "FL": {
|
|
1122
|
-
|
|
1123
|
-
decodeResult.
|
|
1124
|
-
|
|
1125
|
-
code: "FL",
|
|
1126
|
-
label: this.descriptions[match.groups.field],
|
|
1127
|
-
value: decodeResult.raw.flight_level
|
|
1128
|
-
});
|
|
1413
|
+
const flight_level = match.groups.value;
|
|
1414
|
+
decodeResult.raw.altitude = flight_level * 100;
|
|
1415
|
+
ResultFormatter.altitude(decodeResult, decodeResult.raw.altitude);
|
|
1129
1416
|
break;
|
|
1130
1417
|
}
|
|
1131
1418
|
case "FOB": {
|
|
@@ -1359,183 +1646,6 @@ function processUnknown(decodeResult, value) {
|
|
|
1359
1646
|
decodeResult.remaining.text += value;
|
|
1360
1647
|
}
|
|
1361
1648
|
|
|
1362
|
-
// lib/utils/result_formatter.ts
|
|
1363
|
-
var ResultFormatter = class {
|
|
1364
|
-
static altitude(decodeResult, value) {
|
|
1365
|
-
decodeResult.raw.altitude = value;
|
|
1366
|
-
decodeResult.formatted.items.push({
|
|
1367
|
-
type: "altitude",
|
|
1368
|
-
code: "ALT",
|
|
1369
|
-
label: "Altitude",
|
|
1370
|
-
value: `${decodeResult.raw.altitude} feet`
|
|
1371
|
-
});
|
|
1372
|
-
}
|
|
1373
|
-
static flightNumber(decodeResult, value) {
|
|
1374
|
-
decodeResult.raw.flight_number = value;
|
|
1375
|
-
}
|
|
1376
|
-
static departureAirport(decodeResult, value) {
|
|
1377
|
-
decodeResult.raw.departure_icao = value;
|
|
1378
|
-
decodeResult.formatted.items.push({
|
|
1379
|
-
type: "origin",
|
|
1380
|
-
code: "ORG",
|
|
1381
|
-
label: "Origin",
|
|
1382
|
-
value: decodeResult.raw.departure_icao
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
static departureRunway(decodeResult, value) {
|
|
1386
|
-
decodeResult.raw.departure_runway = value;
|
|
1387
|
-
decodeResult.formatted.items.push({
|
|
1388
|
-
type: "runway",
|
|
1389
|
-
code: "DEPRWY",
|
|
1390
|
-
label: "Departure Runway",
|
|
1391
|
-
value: decodeResult.raw.departure_runway
|
|
1392
|
-
});
|
|
1393
|
-
}
|
|
1394
|
-
static arrivalAirport(decodeResult, value) {
|
|
1395
|
-
decodeResult.raw.arrival_icao = value;
|
|
1396
|
-
decodeResult.formatted.items.push({
|
|
1397
|
-
type: "destination",
|
|
1398
|
-
code: "DST",
|
|
1399
|
-
label: "Destination",
|
|
1400
|
-
value: decodeResult.raw.arrival_icao
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
static eta(decodeResult, value) {
|
|
1404
|
-
decodeResult.formatted.items.push({
|
|
1405
|
-
type: "eta",
|
|
1406
|
-
code: "ETA",
|
|
1407
|
-
label: "Estimated Time of Arrival",
|
|
1408
|
-
value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
|
|
1409
|
-
});
|
|
1410
|
-
}
|
|
1411
|
-
static arrivalRunway(decodeResult, value) {
|
|
1412
|
-
decodeResult.raw.arrival_runway = value;
|
|
1413
|
-
decodeResult.formatted.items.push({
|
|
1414
|
-
type: "runway",
|
|
1415
|
-
label: "Arrival Runway",
|
|
1416
|
-
value: decodeResult.raw.arrival_runway
|
|
1417
|
-
});
|
|
1418
|
-
}
|
|
1419
|
-
static currentFuel(decodeResult, value) {
|
|
1420
|
-
decodeResult.raw.fuel_on_board = value;
|
|
1421
|
-
decodeResult.formatted.items.push({
|
|
1422
|
-
type: "fuel_on_board",
|
|
1423
|
-
code: "FOB",
|
|
1424
|
-
label: "Fuel On Board",
|
|
1425
|
-
value: decodeResult.raw.fuel_on_board.toString()
|
|
1426
|
-
});
|
|
1427
|
-
}
|
|
1428
|
-
static remainingFuel(decodeResult, value) {
|
|
1429
|
-
decodeResult.raw.fuel_remaining = value;
|
|
1430
|
-
decodeResult.formatted.items.push({
|
|
1431
|
-
type: "fuel_remaining",
|
|
1432
|
-
label: "Fuel Remaining",
|
|
1433
|
-
value: decodeResult.raw.fuel_remaining.toString()
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
static checksum(decodeResult, value) {
|
|
1437
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1438
|
-
decodeResult.formatted.items.push({
|
|
1439
|
-
type: "message_checksum",
|
|
1440
|
-
code: "CHECKSUM",
|
|
1441
|
-
label: "Message Checksum",
|
|
1442
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1443
|
-
});
|
|
1444
|
-
}
|
|
1445
|
-
static groundspeed(decodeResult, value) {
|
|
1446
|
-
decodeResult.raw.groundspeed = value;
|
|
1447
|
-
decodeResult.formatted.items.push({
|
|
1448
|
-
type: "aircraft_groundspeed",
|
|
1449
|
-
code: "GSPD",
|
|
1450
|
-
label: "Aircraft Groundspeed",
|
|
1451
|
-
value: `${decodeResult.raw.groundspeed}`
|
|
1452
|
-
});
|
|
1453
|
-
}
|
|
1454
|
-
static temperature(decodeResult, value) {
|
|
1455
|
-
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1456
|
-
decodeResult.formatted.items.push({
|
|
1457
|
-
type: "outside_air_temperature",
|
|
1458
|
-
code: "OATEMP",
|
|
1459
|
-
label: "Outside Air Temperature (C)",
|
|
1460
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
static unknown(decodeResult, value) {
|
|
1464
|
-
decodeResult.remaining.text += "," + value;
|
|
1465
|
-
}
|
|
1466
|
-
};
|
|
1467
|
-
|
|
1468
|
-
// lib/utils/route_utils.ts
|
|
1469
|
-
var RouteUtils = class _RouteUtils {
|
|
1470
|
-
static routeToString(route) {
|
|
1471
|
-
let str = "";
|
|
1472
|
-
if (route.name) {
|
|
1473
|
-
str += route.name;
|
|
1474
|
-
}
|
|
1475
|
-
if (route.runway) {
|
|
1476
|
-
str += `(${route.runway})`;
|
|
1477
|
-
}
|
|
1478
|
-
if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
|
|
1479
|
-
str += " starting at ";
|
|
1480
|
-
} else if (str.length !== 0 && route.waypoints) {
|
|
1481
|
-
str += ": ";
|
|
1482
|
-
}
|
|
1483
|
-
if (route.waypoints) {
|
|
1484
|
-
str += _RouteUtils.waypointsToString(route.waypoints);
|
|
1485
|
-
}
|
|
1486
|
-
return str;
|
|
1487
|
-
}
|
|
1488
|
-
static waypointToString(waypoint) {
|
|
1489
|
-
let s = waypoint.name;
|
|
1490
|
-
if (waypoint.latitude && waypoint.longitude) {
|
|
1491
|
-
s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
|
|
1492
|
-
}
|
|
1493
|
-
if (waypoint.offset) {
|
|
1494
|
-
s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
|
|
1495
|
-
}
|
|
1496
|
-
if (waypoint.time && waypoint.timeFormat) {
|
|
1497
|
-
s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
|
|
1498
|
-
}
|
|
1499
|
-
return s;
|
|
1500
|
-
}
|
|
1501
|
-
static getWaypoint(leg) {
|
|
1502
|
-
const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
|
|
1503
|
-
if (regex?.length == 4) {
|
|
1504
|
-
return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
|
|
1505
|
-
}
|
|
1506
|
-
const waypoint = leg.split(",");
|
|
1507
|
-
if (waypoint.length == 2) {
|
|
1508
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(waypoint[1]);
|
|
1509
|
-
if (position) {
|
|
1510
|
-
return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
if (leg.length == 13 || leg.length == 14) {
|
|
1514
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(leg);
|
|
1515
|
-
const name = waypoint.length == 2 ? waypoint[0] : "";
|
|
1516
|
-
if (position) {
|
|
1517
|
-
return { name, latitude: position.latitude, longitude: position.longitude };
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
return { name: leg };
|
|
1521
|
-
}
|
|
1522
|
-
// move out if we want public
|
|
1523
|
-
static timestampToString(time, format) {
|
|
1524
|
-
const date = new Date(time * 1e3);
|
|
1525
|
-
if (format == "tod") {
|
|
1526
|
-
return date.toISOString().slice(11, 19);
|
|
1527
|
-
}
|
|
1528
|
-
return date.toISOString().slice(0, -5) + "Z";
|
|
1529
|
-
}
|
|
1530
|
-
static waypointsToString(waypoints) {
|
|
1531
|
-
let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
|
|
1532
|
-
if (str.startsWith(" > ")) {
|
|
1533
|
-
str = ">>" + str.slice(2);
|
|
1534
|
-
}
|
|
1535
|
-
return str;
|
|
1536
|
-
}
|
|
1537
|
-
};
|
|
1538
|
-
|
|
1539
1649
|
// lib/utils/flight_plan_utils.ts
|
|
1540
1650
|
var FlightPlanUtils = class _FlightPlanUtils {
|
|
1541
1651
|
/**
|
|
@@ -2212,6 +2322,60 @@ function processUnknown2(decodeResult, value) {
|
|
|
2212
2322
|
decodeResult.remaining.text += value;
|
|
2213
2323
|
}
|
|
2214
2324
|
|
|
2325
|
+
// lib/plugins/Label_HX.ts
|
|
2326
|
+
var Label_HX = class extends DecoderPlugin {
|
|
2327
|
+
name = "label-hx";
|
|
2328
|
+
qualifiers() {
|
|
2329
|
+
return {
|
|
2330
|
+
labels: ["HX"],
|
|
2331
|
+
preambles: ["RA FMT LOCATION", "RA FMT 43"]
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
decode(message, options = {}) {
|
|
2335
|
+
const decodeResult = this.defaultResult();
|
|
2336
|
+
decodeResult.decoder.name = this.name;
|
|
2337
|
+
decodeResult.message = message;
|
|
2338
|
+
decodeResult.formatted.description = "Undelivered Uplink Report";
|
|
2339
|
+
const parts = message.text.split(" ");
|
|
2340
|
+
decodeResult.decoded = true;
|
|
2341
|
+
if (parts[2] === "LOCATION") {
|
|
2342
|
+
let latdir = parts[3].substring(0, 1);
|
|
2343
|
+
let latdeg = Number(parts[3].substring(1, 3));
|
|
2344
|
+
let latmin = Number(parts[3].substring(3, 7));
|
|
2345
|
+
let londir = parts[4].substring(0, 1);
|
|
2346
|
+
let londeg = Number(parts[4].substring(1, 4));
|
|
2347
|
+
let lonmin = Number(parts[4].substring(4, 8));
|
|
2348
|
+
decodeResult.raw.position = {
|
|
2349
|
+
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
2350
|
+
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
2351
|
+
};
|
|
2352
|
+
decodeResult.remaining.text = parts.slice(5).join(" ");
|
|
2353
|
+
} else if (parts[2] === "43") {
|
|
2354
|
+
ResultFormatter.departureAirport(decodeResult, parts[3]);
|
|
2355
|
+
decodeResult.remaining.text = parts.slice(4).join(" ");
|
|
2356
|
+
} else {
|
|
2357
|
+
decodeResult.decoded = false;
|
|
2358
|
+
}
|
|
2359
|
+
if (decodeResult.raw.position) {
|
|
2360
|
+
decodeResult.formatted.items.push({
|
|
2361
|
+
type: "aircraft_position",
|
|
2362
|
+
code: "POS",
|
|
2363
|
+
label: "Aircraft Position",
|
|
2364
|
+
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
if (decodeResult.decoded) {
|
|
2368
|
+
if (decodeResult.remaining.text === "")
|
|
2369
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2370
|
+
else
|
|
2371
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2372
|
+
} else {
|
|
2373
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2374
|
+
}
|
|
2375
|
+
return decodeResult;
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
|
|
2215
2379
|
// lib/plugins/Label_SQ.ts
|
|
2216
2380
|
var Label_SQ = class extends DecoderPlugin {
|
|
2217
2381
|
name = "label-sq";
|
|
@@ -2252,11 +2416,13 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2252
2416
|
decodeResult.formatted.items = [
|
|
2253
2417
|
{
|
|
2254
2418
|
type: "network",
|
|
2419
|
+
code: "NETT",
|
|
2255
2420
|
label: "Network",
|
|
2256
2421
|
value: formattedNetwork
|
|
2257
2422
|
},
|
|
2258
2423
|
{
|
|
2259
2424
|
type: "version",
|
|
2425
|
+
code: "VER",
|
|
2260
2426
|
label: "Version",
|
|
2261
2427
|
value: decodeResult.raw.version
|
|
2262
2428
|
}
|
|
@@ -2265,6 +2431,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2265
2431
|
if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
|
|
2266
2432
|
decodeResult.formatted.items.push({
|
|
2267
2433
|
type: "ground_station",
|
|
2434
|
+
code: "GNDSTN",
|
|
2268
2435
|
label: "Ground Station",
|
|
2269
2436
|
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
2270
2437
|
});
|
|
@@ -2272,6 +2439,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2272
2439
|
if (decodeResult.raw.groundStation.iataCode) {
|
|
2273
2440
|
decodeResult.formatted.items.push({
|
|
2274
2441
|
type: "iataCode",
|
|
2442
|
+
code: "IATA",
|
|
2275
2443
|
label: "IATA",
|
|
2276
2444
|
value: decodeResult.raw.groundStation.iataCode
|
|
2277
2445
|
});
|
|
@@ -2279,6 +2447,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2279
2447
|
if (decodeResult.raw.groundStation.icaoCode) {
|
|
2280
2448
|
decodeResult.formatted.items.push({
|
|
2281
2449
|
type: "icaoCode",
|
|
2450
|
+
code: "ICAO",
|
|
2282
2451
|
label: "ICAO",
|
|
2283
2452
|
value: decodeResult.raw.groundStation.icaoCode
|
|
2284
2453
|
});
|
|
@@ -2286,6 +2455,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2286
2455
|
if (decodeResult.raw.groundStation.coordinates.latitude) {
|
|
2287
2456
|
decodeResult.formatted.items.push({
|
|
2288
2457
|
type: "coordinates",
|
|
2458
|
+
code: "COORD",
|
|
2289
2459
|
label: "Ground Station Location",
|
|
2290
2460
|
value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
|
|
2291
2461
|
});
|
|
@@ -2293,6 +2463,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2293
2463
|
if (decodeResult.raw.groundStation.airport) {
|
|
2294
2464
|
decodeResult.formatted.items.push({
|
|
2295
2465
|
type: "airport",
|
|
2466
|
+
code: "APT",
|
|
2296
2467
|
label: "Airport",
|
|
2297
2468
|
value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
|
|
2298
2469
|
});
|
|
@@ -2301,6 +2472,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2301
2472
|
if (decodeResult.raw.vdlFrequency) {
|
|
2302
2473
|
decodeResult.formatted.items.push({
|
|
2303
2474
|
type: "vdlFrequency",
|
|
2475
|
+
code: "VDLFRQ",
|
|
2304
2476
|
label: "VDL Frequency",
|
|
2305
2477
|
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
2306
2478
|
});
|
|
@@ -2457,31 +2629,48 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
2457
2629
|
decode(message, options = {}) {
|
|
2458
2630
|
const decodeResult = this.defaultResult();
|
|
2459
2631
|
decodeResult.decoder.name = this.name;
|
|
2460
|
-
decodeResult.
|
|
2461
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
2462
|
-
decodeResult.raw.wheels_off = message.text.substring(8, 12);
|
|
2463
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
2632
|
+
decodeResult.message = message;
|
|
2464
2633
|
decodeResult.formatted.description = "OFF Report";
|
|
2465
|
-
decodeResult.
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2634
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
2635
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
2636
|
+
decodeResult.raw.wheels_off = message.text.substring(8, 12);
|
|
2637
|
+
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
2638
|
+
decodeResult.raw.day_of_month = message.text.substring(19, 21);
|
|
2639
|
+
decodeResult.raw.wheels_off = message.text.substring(21, 27);
|
|
2640
|
+
let latdir = message.text.substring(27, 28);
|
|
2641
|
+
let latdeg = Number(message.text.substring(28, 30));
|
|
2642
|
+
let latmin = Number(message.text.substring(30, 34));
|
|
2643
|
+
let londir = message.text.substring(34, 35);
|
|
2644
|
+
let londeg = Number(message.text.substring(35, 38));
|
|
2645
|
+
let lonmin = Number(message.text.substring(38, 42));
|
|
2646
|
+
decodeResult.raw.position = {
|
|
2647
|
+
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
2648
|
+
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
2649
|
+
};
|
|
2650
|
+
decodeResult.remaining.text = message.text.substring(42, 45);
|
|
2651
|
+
if (decodeResult.remaining.text !== "---") {
|
|
2652
|
+
ResultFormatter.groundspeed(decodeResult, message.text.substring(45, 48));
|
|
2653
|
+
} else {
|
|
2654
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
2483
2655
|
}
|
|
2484
|
-
|
|
2656
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
2657
|
+
} else {
|
|
2658
|
+
decodeResult.remaining.text = message.text.substring(12);
|
|
2659
|
+
}
|
|
2660
|
+
decodeResult.formatted.items.push({
|
|
2661
|
+
type: "wheels_off",
|
|
2662
|
+
code: "WOFF",
|
|
2663
|
+
label: "Wheels OFF",
|
|
2664
|
+
value: decodeResult.raw.wheels_off
|
|
2665
|
+
});
|
|
2666
|
+
if (decodeResult.raw.position) {
|
|
2667
|
+
decodeResult.formatted.items.push({
|
|
2668
|
+
type: "aircraft_position",
|
|
2669
|
+
code: "POS",
|
|
2670
|
+
label: "Aircraft Position",
|
|
2671
|
+
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2485
2674
|
decodeResult.decoded = true;
|
|
2486
2675
|
if (decodeResult.remaining.text === "")
|
|
2487
2676
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3304,6 +3493,9 @@ var MessageDecoder = class {
|
|
|
3304
3493
|
this.debug = false;
|
|
3305
3494
|
this.registerPlugin(new Label_ColonComma(this));
|
|
3306
3495
|
this.registerPlugin(new Label_5Z(this));
|
|
3496
|
+
this.registerPlugin(new Label_10_LDR(this));
|
|
3497
|
+
this.registerPlugin(new Label_10_POS(this));
|
|
3498
|
+
this.registerPlugin(new Label_10_Slash(this));
|
|
3307
3499
|
this.registerPlugin(new Label_12_N_Space(this));
|
|
3308
3500
|
this.registerPlugin(new Label_15(this));
|
|
3309
3501
|
this.registerPlugin(new Label_15_FST(this));
|
|
@@ -3324,6 +3516,7 @@ var MessageDecoder = class {
|
|
|
3324
3516
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
3325
3517
|
this.registerPlugin(new Label_H1_POS(this));
|
|
3326
3518
|
this.registerPlugin(new Label_H1_WRN(this));
|
|
3519
|
+
this.registerPlugin(new Label_HX(this));
|
|
3327
3520
|
this.registerPlugin(new Label_80(this));
|
|
3328
3521
|
this.registerPlugin(new Label_8E(this));
|
|
3329
3522
|
this.registerPlugin(new Label_1M_Slash(this));
|