@airframes/acars-decoder 1.6.8 → 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 +769 -411
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +769 -411
- 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";
|
|
@@ -119,34 +305,9 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
119
305
|
const rdcRegex = /^(?<from>\w\w\w)(?<to>\w\w\w) (?<unknown1>\d\d) R(?<runway>.+) G(?<unknown2>.+)$/;
|
|
120
306
|
results = remainder.match(rdcRegex);
|
|
121
307
|
if (results) {
|
|
122
|
-
decodeResult
|
|
123
|
-
decodeResult.
|
|
124
|
-
|
|
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
|
-
});
|
|
308
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.from);
|
|
309
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.to);
|
|
310
|
+
ResultFormatter.arrivalRunway(decodeResult, results.groups.runway);
|
|
150
311
|
} else {
|
|
151
312
|
if (options.debug) {
|
|
152
313
|
console.log(`Decoder: Unkown 5Z RDC format: ${remainder}`);
|
|
@@ -169,62 +330,273 @@ var Label_5Z = class extends DecoderPlugin {
|
|
|
169
330
|
}
|
|
170
331
|
};
|
|
171
332
|
|
|
172
|
-
// lib/
|
|
173
|
-
var
|
|
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
|
+
}
|
|
174
440
|
/**
|
|
175
|
-
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
176
|
-
* @param stringCoords - The string of coordinates to decode
|
|
177
441
|
*
|
|
178
|
-
* @
|
|
442
|
+
* @param time HHMMSS
|
|
443
|
+
* @returns seconds since midnight
|
|
179
444
|
*/
|
|
180
|
-
static
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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)}`;
|
|
188
461
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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;
|
|
194
474
|
}
|
|
195
|
-
|
|
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;
|
|
196
487
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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);
|
|
211
527
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if ((
|
|
217
|
-
|
|
218
|
-
results.longitude = (lonDeg + lonMin / 60) * (middleChar === "W" ? -1 : 1);
|
|
219
|
-
} else {
|
|
220
|
-
return;
|
|
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);
|
|
221
534
|
}
|
|
222
|
-
return
|
|
535
|
+
return str;
|
|
223
536
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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: ["/"]
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
decode(message, options = {}) {
|
|
550
|
+
const decodeResult = this.defaultResult();
|
|
551
|
+
decodeResult.decoder.name = this.name;
|
|
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}`);
|
|
558
|
+
}
|
|
559
|
+
decodeResult.remaining.text = message.text;
|
|
560
|
+
decodeResult.decoded = false;
|
|
561
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
562
|
+
return decodeResult;
|
|
563
|
+
}
|
|
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]);
|
|
595
|
+
}
|
|
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,9 +1287,7 @@ 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
|
);
|
|
@@ -999,24 +1305,9 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
999
1305
|
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1000
1306
|
});
|
|
1001
1307
|
}
|
|
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
|
-
});
|
|
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": {
|
|
@@ -1291,194 +1578,73 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
1291
1578
|
const decodeResult = this.defaultResult();
|
|
1292
1579
|
decodeResult.decoder.name = this.name;
|
|
1293
1580
|
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
1294
|
-
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
1295
|
-
decodeResult.formatted.items.push({
|
|
1296
|
-
type: "frequency",
|
|
1297
|
-
label: "Frequency",
|
|
1298
|
-
value: `${decodeResult.raw.frequency} MHz`
|
|
1299
|
-
});
|
|
1300
|
-
decodeResult.decoded = true;
|
|
1301
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
1302
|
-
return decodeResult;
|
|
1303
|
-
}
|
|
1304
|
-
};
|
|
1305
|
-
|
|
1306
|
-
// lib/utils/result_formatter.ts
|
|
1307
|
-
var ResultFormatter = class {
|
|
1308
|
-
static altitude(decodeResult, value) {
|
|
1309
|
-
decodeResult.raw.altitude = value;
|
|
1310
|
-
decodeResult.formatted.items.push({
|
|
1311
|
-
type: "altitude",
|
|
1312
|
-
code: "ALT",
|
|
1313
|
-
label: "Altitude",
|
|
1314
|
-
value: `${decodeResult.raw.altitude} feet`
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
static flightNumber(decodeResult, value) {
|
|
1318
|
-
decodeResult.raw.flight_number = value;
|
|
1319
|
-
}
|
|
1320
|
-
static departureAirport(decodeResult, value) {
|
|
1321
|
-
decodeResult.raw.departure_icao = value;
|
|
1322
|
-
decodeResult.formatted.items.push({
|
|
1323
|
-
type: "origin",
|
|
1324
|
-
code: "ORG",
|
|
1325
|
-
label: "Origin",
|
|
1326
|
-
value: decodeResult.raw.departure_icao
|
|
1327
|
-
});
|
|
1328
|
-
}
|
|
1329
|
-
static departureRunway(decodeResult, value) {
|
|
1330
|
-
decodeResult.raw.departure_runway = value;
|
|
1331
|
-
decodeResult.formatted.items.push({
|
|
1332
|
-
type: "runway",
|
|
1333
|
-
code: "DEPRWY",
|
|
1334
|
-
label: "Departure Runway",
|
|
1335
|
-
value: decodeResult.raw.departure_runway
|
|
1336
|
-
});
|
|
1337
|
-
}
|
|
1338
|
-
static arrivalAirport(decodeResult, value) {
|
|
1339
|
-
decodeResult.raw.arrival_icao = value;
|
|
1340
|
-
decodeResult.formatted.items.push({
|
|
1341
|
-
type: "destination",
|
|
1342
|
-
code: "DST",
|
|
1343
|
-
label: "Destination",
|
|
1344
|
-
value: decodeResult.raw.arrival_icao
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
|
-
static eta(decodeResult, value) {
|
|
1348
|
-
decodeResult.formatted.items.push({
|
|
1349
|
-
type: "eta",
|
|
1350
|
-
code: "ETA",
|
|
1351
|
-
label: "Estimated Time of Arrival",
|
|
1352
|
-
value: value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6)
|
|
1353
|
-
});
|
|
1354
|
-
}
|
|
1355
|
-
static arrivalRunway(decodeResult, value) {
|
|
1356
|
-
decodeResult.raw.arrival_runway = value;
|
|
1357
|
-
decodeResult.formatted.items.push({
|
|
1358
|
-
type: "runway",
|
|
1359
|
-
label: "Arrival Runway",
|
|
1360
|
-
value: decodeResult.raw.arrival_runway
|
|
1361
|
-
});
|
|
1362
|
-
}
|
|
1363
|
-
static currentFuel(decodeResult, value) {
|
|
1364
|
-
decodeResult.raw.fuel_on_board = value;
|
|
1365
|
-
decodeResult.formatted.items.push({
|
|
1366
|
-
type: "fuel_on_board",
|
|
1367
|
-
code: "FOB",
|
|
1368
|
-
label: "Fuel On Board",
|
|
1369
|
-
value: decodeResult.raw.fuel_on_board.toString()
|
|
1370
|
-
});
|
|
1371
|
-
}
|
|
1372
|
-
static remainingFuel(decodeResult, value) {
|
|
1373
|
-
decodeResult.raw.fuel_remaining = value;
|
|
1374
|
-
decodeResult.formatted.items.push({
|
|
1375
|
-
type: "fuel_remaining",
|
|
1376
|
-
label: "Fuel Remaining",
|
|
1377
|
-
value: decodeResult.raw.fuel_remaining.toString()
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
static checksum(decodeResult, value) {
|
|
1381
|
-
decodeResult.raw.checksum = Number("0x" + value);
|
|
1382
|
-
decodeResult.formatted.items.push({
|
|
1383
|
-
type: "message_checksum",
|
|
1384
|
-
code: "CHECKSUM",
|
|
1385
|
-
label: "Message Checksum",
|
|
1386
|
-
value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1389
|
-
static groundspeed(decodeResult, value) {
|
|
1390
|
-
decodeResult.raw.groundspeed = value;
|
|
1391
|
-
decodeResult.formatted.items.push({
|
|
1392
|
-
type: "aircraft_groundspeed",
|
|
1393
|
-
code: "GSPD",
|
|
1394
|
-
label: "Aircraft Groundspeed",
|
|
1395
|
-
value: `${decodeResult.raw.groundspeed}`
|
|
1396
|
-
});
|
|
1397
|
-
}
|
|
1398
|
-
static temperature(decodeResult, value) {
|
|
1399
|
-
decodeResult.raw.outside_air_temperature = Number(value.substring(1)) * (value.charAt(0) === "M" ? -1 : 1);
|
|
1400
|
-
decodeResult.formatted.items.push({
|
|
1401
|
-
type: "outside_air_temperature",
|
|
1402
|
-
code: "OATEMP",
|
|
1403
|
-
label: "Outside Air Temperature (C)",
|
|
1404
|
-
value: `${decodeResult.raw.outside_air_temperature}`
|
|
1581
|
+
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
1582
|
+
decodeResult.formatted.items.push({
|
|
1583
|
+
type: "frequency",
|
|
1584
|
+
label: "Frequency",
|
|
1585
|
+
value: `${decodeResult.raw.frequency} MHz`
|
|
1405
1586
|
});
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
decodeResult
|
|
1587
|
+
decodeResult.decoded = true;
|
|
1588
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
1589
|
+
return decodeResult;
|
|
1409
1590
|
}
|
|
1410
1591
|
};
|
|
1411
1592
|
|
|
1412
|
-
// lib/
|
|
1413
|
-
var
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
str += `(${route.runway})`;
|
|
1421
|
-
}
|
|
1422
|
-
if (str.length !== 0 && route.waypoints && route.waypoints.length === 1) {
|
|
1423
|
-
str += " starting at ";
|
|
1424
|
-
} else if (str.length !== 0 && route.waypoints) {
|
|
1425
|
-
str += ": ";
|
|
1426
|
-
}
|
|
1427
|
-
if (route.waypoints) {
|
|
1428
|
-
str += _RouteUtils.waypointsToString(route.waypoints);
|
|
1429
|
-
}
|
|
1430
|
-
return str;
|
|
1431
|
-
}
|
|
1432
|
-
static waypointToString(waypoint) {
|
|
1433
|
-
let s = waypoint.name;
|
|
1434
|
-
if (waypoint.latitude && waypoint.longitude) {
|
|
1435
|
-
s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
|
|
1436
|
-
}
|
|
1437
|
-
if (waypoint.offset) {
|
|
1438
|
-
s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
|
|
1439
|
-
}
|
|
1440
|
-
if (waypoint.time && waypoint.timeFormat) {
|
|
1441
|
-
s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
|
|
1442
|
-
}
|
|
1443
|
-
return s;
|
|
1593
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
1594
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
1595
|
+
name = "label-h1-flr";
|
|
1596
|
+
qualifiers() {
|
|
1597
|
+
return {
|
|
1598
|
+
labels: ["H1"],
|
|
1599
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
1600
|
+
};
|
|
1444
1601
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
const
|
|
1451
|
-
if (
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1602
|
+
decode(message, options = {}) {
|
|
1603
|
+
let decodeResult = this.defaultResult();
|
|
1604
|
+
decodeResult.decoder.name = this.name;
|
|
1605
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
1606
|
+
decodeResult.message = message;
|
|
1607
|
+
const parts = message.text.split("/FR");
|
|
1608
|
+
if (parts.length > 1) {
|
|
1609
|
+
decodeResult.remaining.text = "";
|
|
1610
|
+
const fields = parts[0].split("/");
|
|
1611
|
+
for (let i = 1; i < fields.length; i++) {
|
|
1612
|
+
const field = fields[i];
|
|
1613
|
+
if (field.startsWith("PN")) {
|
|
1614
|
+
processUnknown(decodeResult, "/" + field);
|
|
1615
|
+
} else {
|
|
1616
|
+
processUnknown(decodeResult, "/" + field);
|
|
1617
|
+
}
|
|
1455
1618
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
const
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1619
|
+
const data = parts[1].substring(0, 20);
|
|
1620
|
+
const msg = parts[1].substring(20);
|
|
1621
|
+
const datetime = data.substring(0, 12);
|
|
1622
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
1623
|
+
processUnknown(decodeResult, data.substring(12));
|
|
1624
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
1625
|
+
decodeResult.raw.fault_message = msg;
|
|
1626
|
+
decodeResult.formatted.items.push({
|
|
1627
|
+
type: "fault",
|
|
1628
|
+
code: "FR",
|
|
1629
|
+
label: "Fault Report",
|
|
1630
|
+
value: decodeResult.raw.fault_message
|
|
1631
|
+
});
|
|
1632
|
+
decodeResult.decoded = true;
|
|
1633
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1634
|
+
} else {
|
|
1635
|
+
if (options.debug) {
|
|
1636
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
1462
1637
|
}
|
|
1638
|
+
decodeResult.remaining.text = message.text;
|
|
1639
|
+
decodeResult.decoded = false;
|
|
1640
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1463
1641
|
}
|
|
1464
|
-
return
|
|
1465
|
-
}
|
|
1466
|
-
// move out if we want public
|
|
1467
|
-
static timestampToString(time, format) {
|
|
1468
|
-
const date = new Date(time * 1e3);
|
|
1469
|
-
if (format == "tod") {
|
|
1470
|
-
return date.toISOString().slice(11, 19);
|
|
1471
|
-
}
|
|
1472
|
-
return date.toISOString().slice(0, -5) + "Z";
|
|
1473
|
-
}
|
|
1474
|
-
static waypointsToString(waypoints) {
|
|
1475
|
-
let str = waypoints.map((x) => _RouteUtils.waypointToString(x)).join(" > ").replaceAll("> >", ">>");
|
|
1476
|
-
if (str.startsWith(" > ")) {
|
|
1477
|
-
str = ">>" + str.slice(2);
|
|
1478
|
-
}
|
|
1479
|
-
return str;
|
|
1642
|
+
return decodeResult;
|
|
1480
1643
|
}
|
|
1481
1644
|
};
|
|
1645
|
+
function processUnknown(decodeResult, value) {
|
|
1646
|
+
decodeResult.remaining.text += value;
|
|
1647
|
+
}
|
|
1482
1648
|
|
|
1483
1649
|
// lib/utils/flight_plan_utils.ts
|
|
1484
1650
|
var FlightPlanUtils = class _FlightPlanUtils {
|
|
@@ -1671,21 +1837,7 @@ var H1Helper = class {
|
|
|
1671
1837
|
const dt = processDT(decodeResult, data2);
|
|
1672
1838
|
allKnownFields = allKnownFields && dt;
|
|
1673
1839
|
} else if (fields[i].startsWith("ID")) {
|
|
1674
|
-
|
|
1675
|
-
decodeResult.raw.tail = data2[0];
|
|
1676
|
-
decodeResult.formatted.items.push({
|
|
1677
|
-
type: "tail",
|
|
1678
|
-
code: "TAIL",
|
|
1679
|
-
label: "Tail",
|
|
1680
|
-
value: decodeResult.raw.tail
|
|
1681
|
-
});
|
|
1682
|
-
if (data2.length > 1) {
|
|
1683
|
-
decodeResult.raw.flight_number = data2[1];
|
|
1684
|
-
}
|
|
1685
|
-
if (data2.length > 2) {
|
|
1686
|
-
allKnownFields = false;
|
|
1687
|
-
decodeResult.remaining.text += "," + data2.slice(2).join(",");
|
|
1688
|
-
}
|
|
1840
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
1689
1841
|
} else if (fields[i].startsWith("LR")) {
|
|
1690
1842
|
const data2 = fields[i].substring(2).split(",");
|
|
1691
1843
|
const lr = processLR(decodeResult, data2);
|
|
@@ -1699,6 +1851,20 @@ var H1Helper = class {
|
|
|
1699
1851
|
} else if (fields[i].startsWith("PS")) {
|
|
1700
1852
|
allKnownFields = false;
|
|
1701
1853
|
decodeResult.remaining.text += fields[i];
|
|
1854
|
+
} else if (fields[i].startsWith("AF")) {
|
|
1855
|
+
const af = processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
1856
|
+
allKnownFields = allKnownFields && af;
|
|
1857
|
+
} else if (fields[i].startsWith("TD")) {
|
|
1858
|
+
const td = processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
1859
|
+
allKnownFields = allKnownFields && td;
|
|
1860
|
+
} else if (fields[i].startsWith("FX")) {
|
|
1861
|
+
decodeResult.raw.free_text = fields[i].substring(2);
|
|
1862
|
+
decodeResult.formatted.items.push({
|
|
1863
|
+
type: "text",
|
|
1864
|
+
code: "TEXT",
|
|
1865
|
+
label: "Free Text",
|
|
1866
|
+
value: decodeResult.raw.free_text
|
|
1867
|
+
});
|
|
1702
1868
|
} else {
|
|
1703
1869
|
decodeResult.remaining.text += "/" + fields[i];
|
|
1704
1870
|
allKnownFields = false;
|
|
@@ -1710,6 +1876,51 @@ var H1Helper = class {
|
|
|
1710
1876
|
return allKnownFields;
|
|
1711
1877
|
}
|
|
1712
1878
|
};
|
|
1879
|
+
function processAirField(decodeResult, data) {
|
|
1880
|
+
if (data.length === 2) {
|
|
1881
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
1882
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
1883
|
+
return true;
|
|
1884
|
+
}
|
|
1885
|
+
decodeResult.remaining.text += "AF/" + data.join(",");
|
|
1886
|
+
return false;
|
|
1887
|
+
}
|
|
1888
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
1889
|
+
if (data.length === 2) {
|
|
1890
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
1891
|
+
decodeResult.formatted.items.push({
|
|
1892
|
+
type: "ptd",
|
|
1893
|
+
code: "ptd",
|
|
1894
|
+
label: "Planned Departure Time",
|
|
1895
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
1896
|
+
});
|
|
1897
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
1898
|
+
decodeResult.formatted.items.push({
|
|
1899
|
+
type: "etd",
|
|
1900
|
+
code: "etd",
|
|
1901
|
+
label: "Estimated Departure Time",
|
|
1902
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
1903
|
+
});
|
|
1904
|
+
return true;
|
|
1905
|
+
}
|
|
1906
|
+
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1909
|
+
function processIdentification(decodeResult, data) {
|
|
1910
|
+
decodeResult.raw.tail = data[0];
|
|
1911
|
+
decodeResult.formatted.items.push({
|
|
1912
|
+
type: "tail",
|
|
1913
|
+
code: "TAIL",
|
|
1914
|
+
label: "Tail",
|
|
1915
|
+
value: decodeResult.raw.tail
|
|
1916
|
+
});
|
|
1917
|
+
if (data.length > 1) {
|
|
1918
|
+
decodeResult.raw.flight_number = data[1];
|
|
1919
|
+
}
|
|
1920
|
+
if (data.length > 2) {
|
|
1921
|
+
decodeResult.raw.mission_number = data[2];
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1713
1924
|
function processDT(decodeResult, data) {
|
|
1714
1925
|
let allKnownFields = true;
|
|
1715
1926
|
if (!decodeResult.raw.arrival_icao) {
|
|
@@ -1787,7 +1998,7 @@ function processDC(decodeResult, data) {
|
|
|
1787
1998
|
}
|
|
1788
1999
|
function processPS(decodeResult, data) {
|
|
1789
2000
|
let allKnownFields = true;
|
|
1790
|
-
const position = CoordinateUtils.
|
|
2001
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1791
2002
|
if (position) {
|
|
1792
2003
|
decodeResult.raw.position = position;
|
|
1793
2004
|
decodeResult.formatted.items.push({
|
|
@@ -1823,7 +2034,7 @@ function processPS(decodeResult, data) {
|
|
|
1823
2034
|
}
|
|
1824
2035
|
function processPosition2(decodeResult, data) {
|
|
1825
2036
|
let allKnownFields = true;
|
|
1826
|
-
const position = CoordinateUtils.
|
|
2037
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
1827
2038
|
if (position) {
|
|
1828
2039
|
decodeResult.raw.position = position;
|
|
1829
2040
|
decodeResult.formatted.items.push({
|
|
@@ -1905,6 +2116,67 @@ var Label_H1_FPN = class extends DecoderPlugin {
|
|
|
1905
2116
|
}
|
|
1906
2117
|
};
|
|
1907
2118
|
|
|
2119
|
+
// lib/plugins/Label_H1_FTX.ts
|
|
2120
|
+
var Label_H1_FTX = class extends DecoderPlugin {
|
|
2121
|
+
name = "label-h1-ftx";
|
|
2122
|
+
qualifiers() {
|
|
2123
|
+
return {
|
|
2124
|
+
labels: ["H1"],
|
|
2125
|
+
preambles: ["FTX", "- #MDFTX"]
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
decode(message, options = {}) {
|
|
2129
|
+
let decodeResult = this.defaultResult();
|
|
2130
|
+
decodeResult.decoder.name = this.name;
|
|
2131
|
+
decodeResult.formatted.description = "Free Text";
|
|
2132
|
+
decodeResult.message = message;
|
|
2133
|
+
decodeResult.remaining.text = "";
|
|
2134
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2135
|
+
decodeResult.decoded = true;
|
|
2136
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2137
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2138
|
+
if (options?.debug) {
|
|
2139
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2140
|
+
}
|
|
2141
|
+
decodeResult.remaining.text = message.text;
|
|
2142
|
+
decodeResult.decoded = false;
|
|
2143
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2144
|
+
}
|
|
2145
|
+
return decodeResult;
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
|
|
2149
|
+
// lib/plugins/Label_H1_INI.ts
|
|
2150
|
+
var Label_H1_INI = class extends DecoderPlugin {
|
|
2151
|
+
// eslint-disable-line camelcase
|
|
2152
|
+
name = "label-h1-ini";
|
|
2153
|
+
qualifiers() {
|
|
2154
|
+
return {
|
|
2155
|
+
labels: ["H1"],
|
|
2156
|
+
preambles: ["INI", "- #MDINI"]
|
|
2157
|
+
};
|
|
2158
|
+
}
|
|
2159
|
+
decode(message, options = {}) {
|
|
2160
|
+
const decodeResult = this.defaultResult();
|
|
2161
|
+
decodeResult.decoder.name = this.name;
|
|
2162
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2163
|
+
decodeResult.message = message;
|
|
2164
|
+
decodeResult.remaining.text = "";
|
|
2165
|
+
const fulllyDecoded = H1Helper.decodeH1Message(decodeResult, message.text);
|
|
2166
|
+
decodeResult.decoded = true;
|
|
2167
|
+
decodeResult.decoder.decodeLevel = fulllyDecoded ? "full" : "partial";
|
|
2168
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2169
|
+
if (options?.debug) {
|
|
2170
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2171
|
+
}
|
|
2172
|
+
decodeResult.remaining.text = message.text;
|
|
2173
|
+
decodeResult.decoded = false;
|
|
2174
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2175
|
+
}
|
|
2176
|
+
return decodeResult;
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
|
|
1908
2180
|
// lib/plugins/Label_H1_OHMA.ts
|
|
1909
2181
|
import * as zlib from "minizlib";
|
|
1910
2182
|
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
@@ -2015,16 +2287,16 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
2015
2287
|
for (let i = 1; i < fields.length; i++) {
|
|
2016
2288
|
const field = fields[i];
|
|
2017
2289
|
if (field.startsWith("PN")) {
|
|
2018
|
-
|
|
2290
|
+
processUnknown2(decodeResult, "/" + field);
|
|
2019
2291
|
} else {
|
|
2020
|
-
|
|
2292
|
+
processUnknown2(decodeResult, "/" + field);
|
|
2021
2293
|
}
|
|
2022
2294
|
}
|
|
2023
2295
|
const data = parts[1].substring(0, 20);
|
|
2024
2296
|
const msg = parts[1].substring(20);
|
|
2025
2297
|
const datetime = data.substring(0, 12);
|
|
2026
2298
|
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2027
|
-
|
|
2299
|
+
processUnknown2(decodeResult, data.substring(12));
|
|
2028
2300
|
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2029
2301
|
decodeResult.raw.warning_message = msg;
|
|
2030
2302
|
decodeResult.formatted.items.push({
|
|
@@ -2046,10 +2318,64 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
2046
2318
|
return decodeResult;
|
|
2047
2319
|
}
|
|
2048
2320
|
};
|
|
2049
|
-
function
|
|
2321
|
+
function processUnknown2(decodeResult, value) {
|
|
2050
2322
|
decodeResult.remaining.text += value;
|
|
2051
2323
|
}
|
|
2052
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
|
+
|
|
2053
2379
|
// lib/plugins/Label_SQ.ts
|
|
2054
2380
|
var Label_SQ = class extends DecoderPlugin {
|
|
2055
2381
|
name = "label-sq";
|
|
@@ -2090,11 +2416,13 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2090
2416
|
decodeResult.formatted.items = [
|
|
2091
2417
|
{
|
|
2092
2418
|
type: "network",
|
|
2419
|
+
code: "NETT",
|
|
2093
2420
|
label: "Network",
|
|
2094
2421
|
value: formattedNetwork
|
|
2095
2422
|
},
|
|
2096
2423
|
{
|
|
2097
2424
|
type: "version",
|
|
2425
|
+
code: "VER",
|
|
2098
2426
|
label: "Version",
|
|
2099
2427
|
value: decodeResult.raw.version
|
|
2100
2428
|
}
|
|
@@ -2103,6 +2431,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2103
2431
|
if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
|
|
2104
2432
|
decodeResult.formatted.items.push({
|
|
2105
2433
|
type: "ground_station",
|
|
2434
|
+
code: "GNDSTN",
|
|
2106
2435
|
label: "Ground Station",
|
|
2107
2436
|
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
2108
2437
|
});
|
|
@@ -2110,6 +2439,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2110
2439
|
if (decodeResult.raw.groundStation.iataCode) {
|
|
2111
2440
|
decodeResult.formatted.items.push({
|
|
2112
2441
|
type: "iataCode",
|
|
2442
|
+
code: "IATA",
|
|
2113
2443
|
label: "IATA",
|
|
2114
2444
|
value: decodeResult.raw.groundStation.iataCode
|
|
2115
2445
|
});
|
|
@@ -2117,6 +2447,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2117
2447
|
if (decodeResult.raw.groundStation.icaoCode) {
|
|
2118
2448
|
decodeResult.formatted.items.push({
|
|
2119
2449
|
type: "icaoCode",
|
|
2450
|
+
code: "ICAO",
|
|
2120
2451
|
label: "ICAO",
|
|
2121
2452
|
value: decodeResult.raw.groundStation.icaoCode
|
|
2122
2453
|
});
|
|
@@ -2124,6 +2455,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2124
2455
|
if (decodeResult.raw.groundStation.coordinates.latitude) {
|
|
2125
2456
|
decodeResult.formatted.items.push({
|
|
2126
2457
|
type: "coordinates",
|
|
2458
|
+
code: "COORD",
|
|
2127
2459
|
label: "Ground Station Location",
|
|
2128
2460
|
value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
|
|
2129
2461
|
});
|
|
@@ -2131,6 +2463,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2131
2463
|
if (decodeResult.raw.groundStation.airport) {
|
|
2132
2464
|
decodeResult.formatted.items.push({
|
|
2133
2465
|
type: "airport",
|
|
2466
|
+
code: "APT",
|
|
2134
2467
|
label: "Airport",
|
|
2135
2468
|
value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
|
|
2136
2469
|
});
|
|
@@ -2139,6 +2472,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2139
2472
|
if (decodeResult.raw.vdlFrequency) {
|
|
2140
2473
|
decodeResult.formatted.items.push({
|
|
2141
2474
|
type: "vdlFrequency",
|
|
2475
|
+
code: "VDLFRQ",
|
|
2142
2476
|
label: "VDL Frequency",
|
|
2143
2477
|
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
2144
2478
|
});
|
|
@@ -2295,31 +2629,48 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
2295
2629
|
decode(message, options = {}) {
|
|
2296
2630
|
const decodeResult = this.defaultResult();
|
|
2297
2631
|
decodeResult.decoder.name = this.name;
|
|
2298
|
-
decodeResult.
|
|
2299
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
2300
|
-
decodeResult.raw.wheels_off = message.text.substring(8, 12);
|
|
2301
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
2632
|
+
decodeResult.message = message;
|
|
2302
2633
|
decodeResult.formatted.description = "OFF Report";
|
|
2303
|
-
decodeResult.
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
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));
|
|
2321
2655
|
}
|
|
2322
|
-
|
|
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
|
+
}
|
|
2323
2674
|
decodeResult.decoded = true;
|
|
2324
2675
|
if (decodeResult.remaining.text === "")
|
|
2325
2676
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3142,6 +3493,9 @@ var MessageDecoder = class {
|
|
|
3142
3493
|
this.debug = false;
|
|
3143
3494
|
this.registerPlugin(new Label_ColonComma(this));
|
|
3144
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));
|
|
3145
3499
|
this.registerPlugin(new Label_12_N_Space(this));
|
|
3146
3500
|
this.registerPlugin(new Label_15(this));
|
|
3147
3501
|
this.registerPlugin(new Label_15_FST(this));
|
|
@@ -3156,9 +3510,13 @@ var MessageDecoder = class {
|
|
|
3156
3510
|
this.registerPlugin(new Label_44_POS(this));
|
|
3157
3511
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
3158
3512
|
this.registerPlugin(new Label_H1_FPN(this));
|
|
3513
|
+
this.registerPlugin(new Label_H1_FLR(this));
|
|
3514
|
+
this.registerPlugin(new Label_H1_FTX(this));
|
|
3515
|
+
this.registerPlugin(new Label_H1_INI(this));
|
|
3159
3516
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
3160
3517
|
this.registerPlugin(new Label_H1_POS(this));
|
|
3161
3518
|
this.registerPlugin(new Label_H1_WRN(this));
|
|
3519
|
+
this.registerPlugin(new Label_HX(this));
|
|
3162
3520
|
this.registerPlugin(new Label_80(this));
|
|
3163
3521
|
this.registerPlugin(new Label_8E(this));
|
|
3164
3522
|
this.registerPlugin(new Label_1M_Slash(this));
|