@airframes/acars-decoder 1.6.13 → 1.6.14
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 +747 -714
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +747 -714
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2150,775 +2150,807 @@ var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
|
2150
2150
|
}
|
|
2151
2151
|
};
|
|
2152
2152
|
|
|
2153
|
-
// lib/
|
|
2154
|
-
var
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
let
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2153
|
+
// lib/utils/flight_plan_utils.ts
|
|
2154
|
+
var FlightPlanUtils = class _FlightPlanUtils {
|
|
2155
|
+
/**
|
|
2156
|
+
* Processes flight plan data
|
|
2157
|
+
*
|
|
2158
|
+
* Expected format is [header, key1, val1, ... keyN, valN]
|
|
2159
|
+
*
|
|
2160
|
+
* @param decodeResult - results
|
|
2161
|
+
* @param data - original message split by ':'
|
|
2162
|
+
* @returns whether all fields were processed or not
|
|
2163
|
+
*/
|
|
2164
|
+
static processFlightPlan(decodeResult, data) {
|
|
2165
|
+
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2166
|
+
for (let i = 1; i < data.length; i += 2) {
|
|
2167
|
+
const key = data[i];
|
|
2168
|
+
const value = data[i + 1];
|
|
2169
|
+
switch (key) {
|
|
2170
|
+
case "A":
|
|
2171
|
+
addProcedure(decodeResult, value, "arrival");
|
|
2172
|
+
break;
|
|
2173
|
+
case "AA":
|
|
2174
|
+
addArrivalAirport(decodeResult, value);
|
|
2175
|
+
break;
|
|
2176
|
+
case "AP":
|
|
2177
|
+
addProcedure(decodeResult, value, "approach");
|
|
2178
|
+
break;
|
|
2179
|
+
case "CR":
|
|
2180
|
+
addCompanyRoute(decodeResult, value);
|
|
2181
|
+
break;
|
|
2182
|
+
case "D":
|
|
2183
|
+
addProcedure(decodeResult, value, "departure");
|
|
2184
|
+
break;
|
|
2185
|
+
case "DA":
|
|
2186
|
+
addDepartureAirport(decodeResult, value);
|
|
2187
|
+
break;
|
|
2188
|
+
case "F":
|
|
2189
|
+
addRoute(decodeResult, value);
|
|
2190
|
+
break;
|
|
2191
|
+
case "R":
|
|
2192
|
+
addRunway(decodeResult, value);
|
|
2193
|
+
break;
|
|
2194
|
+
// case 'WS': // something about routes, has altitude, so current parsing won't work
|
|
2195
|
+
// break;
|
|
2196
|
+
default:
|
|
2197
|
+
if (allKnownFields) {
|
|
2198
|
+
decodeResult.remaining.text = "";
|
|
2199
|
+
allKnownFields = false;
|
|
2200
|
+
}
|
|
2201
|
+
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2202
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2192
2203
|
}
|
|
2193
|
-
ResultFormatter.checksum(decodeResult, fields[32]);
|
|
2194
|
-
ResultFormatter.unknownArr(decodeResult, [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter((f) => f != ""));
|
|
2195
|
-
} else {
|
|
2196
|
-
decodeResult.decoded = false;
|
|
2197
|
-
ResultFormatter.unknown(decodeResult, text);
|
|
2198
2204
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2205
|
+
return allKnownFields;
|
|
2206
|
+
}
|
|
2207
|
+
static parseHeader(decodeResult, header) {
|
|
2208
|
+
let allKnownFields = true;
|
|
2209
|
+
if (header.startsWith("RF")) {
|
|
2210
|
+
decodeResult.formatted.items.push({
|
|
2211
|
+
type: "status",
|
|
2212
|
+
code: "ROUTE_STATUS",
|
|
2213
|
+
label: "Route Status",
|
|
2214
|
+
value: "Route Filed"
|
|
2215
|
+
});
|
|
2216
|
+
decodeResult.raw.route_status = "RF";
|
|
2217
|
+
if (header.length > 2) {
|
|
2218
|
+
addRoute(decodeResult, header.substring(2));
|
|
2219
|
+
}
|
|
2220
|
+
} else if (header.startsWith("RP")) {
|
|
2221
|
+
decodeResult.raw.route_status = "RP";
|
|
2222
|
+
decodeResult.formatted.items.push({
|
|
2223
|
+
type: "status",
|
|
2224
|
+
code: "ROUTE_STATUS",
|
|
2225
|
+
label: "Route Status",
|
|
2226
|
+
value: "Route Planned"
|
|
2227
|
+
});
|
|
2228
|
+
decodeResult.raw.route_status = header;
|
|
2229
|
+
} else if (header.startsWith("RI")) {
|
|
2230
|
+
decodeResult.raw.route_status = "RI";
|
|
2231
|
+
decodeResult.formatted.items.push({
|
|
2232
|
+
type: "status",
|
|
2233
|
+
code: "ROUTE_STATUS",
|
|
2234
|
+
label: "Route Status",
|
|
2235
|
+
value: "Route Inactive"
|
|
2236
|
+
});
|
|
2204
2237
|
} else {
|
|
2205
|
-
decodeResult.
|
|
2238
|
+
decodeResult.remaining.text += header;
|
|
2239
|
+
allKnownFields = false;
|
|
2206
2240
|
}
|
|
2207
|
-
return
|
|
2241
|
+
return allKnownFields;
|
|
2208
2242
|
}
|
|
2209
2243
|
};
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
FL: "Flight Level",
|
|
2220
|
-
HDG: "Heading",
|
|
2221
|
-
MCH: "Aircraft Speed",
|
|
2222
|
-
NWYP: "Next Waypoint",
|
|
2223
|
-
POS: "Aircraft Position",
|
|
2224
|
-
SAT: "Static Air Temperature",
|
|
2225
|
-
SWND: "Wind Speed",
|
|
2226
|
-
TAS: "True Airspeed",
|
|
2227
|
-
WYP: "Waypoint"
|
|
2228
|
-
};
|
|
2229
|
-
qualifiers() {
|
|
2230
|
-
return {
|
|
2231
|
-
labels: ["80"],
|
|
2232
|
-
preambles: ["3N01 POSRPT"]
|
|
2233
|
-
};
|
|
2244
|
+
function addArrivalAirport(decodeResult, value) {
|
|
2245
|
+
ResultFormatter.arrivalAirport(decodeResult, value);
|
|
2246
|
+
}
|
|
2247
|
+
function addDepartureAirport(decodeResult, value) {
|
|
2248
|
+
ResultFormatter.departureAirport(decodeResult, value);
|
|
2249
|
+
}
|
|
2250
|
+
function addRunway(decodeResult, value) {
|
|
2251
|
+
if (value.length === 8) {
|
|
2252
|
+
ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
|
|
2234
2253
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2245
|
-
return decodeResult;
|
|
2246
|
-
}
|
|
2247
|
-
if (results && results.length > 0) {
|
|
2248
|
-
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
2249
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
2250
|
-
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
2251
|
-
if (results.groups.agate) {
|
|
2252
|
-
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
2253
|
-
decodeResult.formatted.items.push({
|
|
2254
|
-
type: "arrival_gate",
|
|
2255
|
-
code: "ARG",
|
|
2256
|
-
label: "Arrival Gate",
|
|
2257
|
-
value: `${results.groups.agate}`
|
|
2258
|
-
});
|
|
2259
|
-
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
2260
|
-
decodeResult.formatted.items.push({
|
|
2261
|
-
type: "scheduled_time_of_arrival",
|
|
2262
|
-
code: "STA",
|
|
2263
|
-
label: "Scheduled Time of Arrival",
|
|
2264
|
-
value: `${results.groups.sta}`
|
|
2265
|
-
});
|
|
2266
|
-
}
|
|
2267
|
-
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
2268
|
-
const remainingParts = parts.slice(1);
|
|
2269
|
-
for (const part of remainingParts) {
|
|
2270
|
-
const matches = part.matchAll(posRptRegex);
|
|
2271
|
-
for (const match of matches) {
|
|
2272
|
-
switch (match.groups?.field) {
|
|
2273
|
-
case "ALT": {
|
|
2274
|
-
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
2275
|
-
break;
|
|
2276
|
-
}
|
|
2277
|
-
case "DWND": {
|
|
2278
|
-
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
2279
|
-
decodeResult.formatted.items.push({
|
|
2280
|
-
type: "wind_direction",
|
|
2281
|
-
code: "DWND",
|
|
2282
|
-
label: this.descriptions[match.groups.field],
|
|
2283
|
-
value: decodeResult.raw.wind_direction
|
|
2284
|
-
});
|
|
2285
|
-
break;
|
|
2286
|
-
}
|
|
2287
|
-
case "FL": {
|
|
2288
|
-
const flight_level = Number(match.groups.value);
|
|
2289
|
-
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
2290
|
-
break;
|
|
2291
|
-
}
|
|
2292
|
-
case "FOB": {
|
|
2293
|
-
const fob = Number(match.groups.value);
|
|
2294
|
-
if (!isNaN(fob)) {
|
|
2295
|
-
ResultFormatter.currentFuel(decodeResult, fob);
|
|
2296
|
-
}
|
|
2297
|
-
break;
|
|
2298
|
-
}
|
|
2299
|
-
case "HDG": {
|
|
2300
|
-
ResultFormatter.heading(decodeResult, Number(match.groups.value));
|
|
2301
|
-
break;
|
|
2302
|
-
}
|
|
2303
|
-
case "MCH": {
|
|
2304
|
-
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2305
|
-
decodeResult.formatted.items.push({
|
|
2306
|
-
type: "mach",
|
|
2307
|
-
code: "MCH",
|
|
2308
|
-
label: this.descriptions[match.groups.field],
|
|
2309
|
-
value: `${decodeResult.raw.mach} Mach`
|
|
2310
|
-
});
|
|
2311
|
-
break;
|
|
2312
|
-
}
|
|
2313
|
-
case "NWYP": {
|
|
2314
|
-
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2315
|
-
decodeResult.formatted.items.push({
|
|
2316
|
-
type: "next_waypoint",
|
|
2317
|
-
code: "NWYP",
|
|
2318
|
-
label: this.descriptions[match.groups.field],
|
|
2319
|
-
value: decodeResult.raw.next_waypoint
|
|
2320
|
-
});
|
|
2321
|
-
break;
|
|
2322
|
-
}
|
|
2323
|
-
case "POS": {
|
|
2324
|
-
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2325
|
-
const posResult = match.groups.value.match(posRegex);
|
|
2326
|
-
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2327
|
-
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2328
|
-
const position = {
|
|
2329
|
-
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2330
|
-
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2331
|
-
};
|
|
2332
|
-
ResultFormatter.position(decodeResult, position);
|
|
2333
|
-
break;
|
|
2334
|
-
}
|
|
2335
|
-
case "SWND": {
|
|
2336
|
-
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2337
|
-
decodeResult.formatted.items.push({
|
|
2338
|
-
type: "wind_speed",
|
|
2339
|
-
code: "SWND",
|
|
2340
|
-
label: this.descriptions[match.groups.field],
|
|
2341
|
-
value: decodeResult.raw.wind_speed
|
|
2342
|
-
});
|
|
2343
|
-
break;
|
|
2344
|
-
}
|
|
2345
|
-
default: {
|
|
2346
|
-
if (match.groups?.field != void 0) {
|
|
2347
|
-
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2348
|
-
decodeResult.formatted.items.push({
|
|
2349
|
-
type: match.groups.field,
|
|
2350
|
-
code: match.groups.field,
|
|
2351
|
-
label: description || `Unknown (${match.groups.field})`,
|
|
2352
|
-
value: `${match.groups.value}`
|
|
2353
|
-
});
|
|
2354
|
-
}
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
}
|
|
2358
|
-
}
|
|
2359
|
-
decodeResult.decoded = true;
|
|
2360
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2361
|
-
}
|
|
2362
|
-
return decodeResult;
|
|
2254
|
+
ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
|
|
2255
|
+
}
|
|
2256
|
+
function addRoute(decodeResult, value) {
|
|
2257
|
+
const route = value.split(".");
|
|
2258
|
+
ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
|
|
2259
|
+
}
|
|
2260
|
+
function addProcedure(decodeResult, value, type) {
|
|
2261
|
+
if (decodeResult.raw.procedures === void 0) {
|
|
2262
|
+
decodeResult.raw.procedures = [];
|
|
2363
2263
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
name = "label-83";
|
|
2369
|
-
qualifiers() {
|
|
2370
|
-
return {
|
|
2371
|
-
labels: ["83"]
|
|
2372
|
-
};
|
|
2264
|
+
const data = value.split(".");
|
|
2265
|
+
let waypoints;
|
|
2266
|
+
if (data.length > 1) {
|
|
2267
|
+
waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
|
|
2373
2268
|
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2269
|
+
const route = { name: data[0], waypoints };
|
|
2270
|
+
decodeResult.raw.procedures.push({ type, route });
|
|
2271
|
+
const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
|
|
2272
|
+
let procedureValue = route.name;
|
|
2273
|
+
decodeResult.formatted.items.push({
|
|
2274
|
+
type: `procedure`,
|
|
2275
|
+
code: "proc",
|
|
2276
|
+
label: `${procedureName} Procedure`,
|
|
2277
|
+
value: RouteUtils.routeToString(route)
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
function addCompanyRoute(decodeResult, value) {
|
|
2281
|
+
const segments = value.split(".");
|
|
2282
|
+
const parens_idx = segments[0].indexOf("(");
|
|
2283
|
+
let name;
|
|
2284
|
+
let runway;
|
|
2285
|
+
if (parens_idx === -1) {
|
|
2286
|
+
name = segments[0];
|
|
2287
|
+
} else {
|
|
2288
|
+
name = segments[0].slice(0, parens_idx);
|
|
2289
|
+
runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
|
|
2290
|
+
}
|
|
2291
|
+
let waypoints;
|
|
2292
|
+
if (segments.length > 1) {
|
|
2293
|
+
waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
|
|
2294
|
+
}
|
|
2295
|
+
decodeResult.raw.company_route = {
|
|
2296
|
+
name,
|
|
2297
|
+
runway,
|
|
2298
|
+
waypoints
|
|
2299
|
+
};
|
|
2300
|
+
decodeResult.formatted.items.push({
|
|
2301
|
+
type: "company_route",
|
|
2302
|
+
code: "CR",
|
|
2303
|
+
label: "Company Route",
|
|
2304
|
+
value: RouteUtils.routeToString(decodeResult.raw.company_route)
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
// lib/utils/h1_helper.ts
|
|
2309
|
+
var H1Helper = class {
|
|
2310
|
+
static decodeH1Message(decodeResult, message) {
|
|
2311
|
+
const checksum = message.slice(-4);
|
|
2312
|
+
const data = message.slice(0, message.length - 4);
|
|
2313
|
+
const fields = data.split("/");
|
|
2314
|
+
parseMessageType(decodeResult, fields[0]);
|
|
2315
|
+
for (let i = 1; i < fields.length; ++i) {
|
|
2316
|
+
if (fields[i].startsWith("FN")) {
|
|
2317
|
+
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2318
|
+
} else if (fields[i].startsWith("SN")) {
|
|
2319
|
+
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2320
|
+
} else if (fields[i].startsWith("DC")) {
|
|
2321
|
+
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2322
|
+
} else if (fields[i].startsWith("TS")) {
|
|
2323
|
+
const ts = fields[i].substring(2).split(",");
|
|
2324
|
+
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2325
|
+
if (Number.isNaN(time)) {
|
|
2326
|
+
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2327
|
+
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2328
|
+
}
|
|
2329
|
+
decodeResult.raw.message_date = ts[1];
|
|
2330
|
+
decodeResult.raw.message_timestamp = time;
|
|
2331
|
+
} else if (fields[i].startsWith("PS")) {
|
|
2332
|
+
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2333
|
+
} else if (fields[i].startsWith("DT")) {
|
|
2334
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2335
|
+
processDT(decodeResult, data2);
|
|
2336
|
+
} else if (fields[i].startsWith("ID")) {
|
|
2337
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2338
|
+
} else if (fields[i].startsWith("LR")) {
|
|
2339
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2340
|
+
processLR(decodeResult, data2);
|
|
2341
|
+
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2342
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2343
|
+
} else if (fields[i].startsWith("PR")) {
|
|
2344
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2345
|
+
} else if (fields[i].startsWith("AF")) {
|
|
2346
|
+
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2347
|
+
} else if (fields[i].startsWith("TD")) {
|
|
2348
|
+
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2349
|
+
} else if (fields[i].startsWith("FX")) {
|
|
2350
|
+
ResultFormatter.freetext(decodeResult, fields[i].substring(2));
|
|
2351
|
+
} else if (fields[i].startsWith("ET")) {
|
|
2352
|
+
if (fields[i].length === 7) {
|
|
2353
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3) + "00"));
|
|
2354
|
+
} else if (fields[i].length === 8) {
|
|
2355
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4) + "00"));
|
|
2356
|
+
} else {
|
|
2357
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2358
|
+
}
|
|
2422
2359
|
} else {
|
|
2423
|
-
decodeResult
|
|
2424
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2360
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2425
2361
|
}
|
|
2426
2362
|
}
|
|
2427
|
-
if (decodeResult.
|
|
2428
|
-
|
|
2429
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2430
|
-
else
|
|
2431
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2432
|
-
} else {
|
|
2433
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2363
|
+
if (decodeResult.formatted.items.length > 0) {
|
|
2364
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
2434
2365
|
}
|
|
2435
|
-
return
|
|
2366
|
+
return true;
|
|
2436
2367
|
}
|
|
2437
2368
|
};
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
labels: ["8E"]
|
|
2445
|
-
};
|
|
2446
|
-
}
|
|
2447
|
-
decode(message, options = {}) {
|
|
2448
|
-
const decodeResult = this.defaultResult();
|
|
2449
|
-
decodeResult.decoder.name = this.name;
|
|
2450
|
-
decodeResult.formatted.description = "ETA Report";
|
|
2451
|
-
decodeResult.message = message;
|
|
2452
|
-
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2453
|
-
const results = message.text.match(regex);
|
|
2454
|
-
if (results?.groups) {
|
|
2455
|
-
if (options.debug) {
|
|
2456
|
-
console.log(`Label 8E ETA: groups`);
|
|
2457
|
-
console.log(results.groups);
|
|
2458
|
-
}
|
|
2459
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2460
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2461
|
-
}
|
|
2462
|
-
decodeResult.decoded = true;
|
|
2463
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2464
|
-
return decodeResult;
|
|
2369
|
+
function processAirField(decodeResult, data) {
|
|
2370
|
+
if (data.length === 2) {
|
|
2371
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
2372
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
2373
|
+
} else {
|
|
2374
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
|
|
2465
2375
|
}
|
|
2466
|
-
}
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2376
|
+
}
|
|
2377
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
2378
|
+
if (data.length === 2) {
|
|
2379
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
2380
|
+
decodeResult.formatted.items.push({
|
|
2381
|
+
type: "ptd",
|
|
2382
|
+
code: "ptd",
|
|
2383
|
+
label: "Planned Departure Time",
|
|
2384
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
2385
|
+
});
|
|
2386
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
2387
|
+
decodeResult.formatted.items.push({
|
|
2388
|
+
type: "etd",
|
|
2389
|
+
code: "etd",
|
|
2390
|
+
label: "Estimated Departure Time",
|
|
2391
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2392
|
+
});
|
|
2393
|
+
} else {
|
|
2394
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
function processIdentification(decodeResult, data) {
|
|
2398
|
+
ResultFormatter.tail(decodeResult, data[0]);
|
|
2399
|
+
if (data.length > 1) {
|
|
2400
|
+
decodeResult.raw.flight_number = data[1];
|
|
2401
|
+
}
|
|
2402
|
+
if (data.length > 2) {
|
|
2403
|
+
decodeResult.raw.mission_number = data[2];
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
function processDT(decodeResult, data) {
|
|
2407
|
+
if (!decodeResult.raw.arrival_icao) {
|
|
2408
|
+
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2409
|
+
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2410
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2411
|
+
}
|
|
2412
|
+
if (data.length > 1) {
|
|
2413
|
+
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2414
|
+
}
|
|
2415
|
+
if (data.length > 2) {
|
|
2416
|
+
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2417
|
+
}
|
|
2418
|
+
if (data.length > 3) {
|
|
2419
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2420
|
+
}
|
|
2421
|
+
if (data.length > 4) {
|
|
2422
|
+
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2423
|
+
}
|
|
2424
|
+
if (data.length > 5) {
|
|
2425
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
function processLR(decodeResult, data) {
|
|
2429
|
+
if (data.length === 19) {
|
|
2430
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2431
|
+
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
2432
|
+
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
2433
|
+
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2434
|
+
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2435
|
+
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2436
|
+
} else {
|
|
2437
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
function parseMessageType(decodeResult, messageType) {
|
|
2441
|
+
const parts = messageType.split("#");
|
|
2442
|
+
if (parts.length == 1) {
|
|
2443
|
+
const type = parts[0].substring(0, 3);
|
|
2444
|
+
if (type === "POS" && parts[0].length !== 3) {
|
|
2445
|
+
processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
2446
|
+
}
|
|
2447
|
+
return processMessageType(decodeResult, type);
|
|
2448
|
+
} else if (parts.length == 2) {
|
|
2449
|
+
if (parts[0].length > 0) {
|
|
2450
|
+
ResultFormatter.unknown(decodeResult, parts[0].substring(0, 3));
|
|
2451
|
+
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
2452
|
+
ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
|
|
2453
|
+
}
|
|
2454
|
+
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
2455
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
2456
|
+
processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
2457
|
+
}
|
|
2458
|
+
processMessageType(decodeResult, type);
|
|
2459
|
+
} else {
|
|
2460
|
+
ResultFormatter.unknown(decodeResult, messageType);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
function processMessageType(decodeResult, type) {
|
|
2464
|
+
if (type === "FPN") {
|
|
2465
|
+
decodeResult.formatted.description = "Flight Plan";
|
|
2466
|
+
} else if (type === "FTX") {
|
|
2467
|
+
decodeResult.formatted.description = "Free Text";
|
|
2468
|
+
} else if (type === "INI") {
|
|
2469
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2470
|
+
} else if (type === "POS") {
|
|
2471
|
+
decodeResult.formatted.description = "Position Report";
|
|
2472
|
+
} else if (type === "PRG") {
|
|
2473
|
+
decodeResult.formatted.description = "Progress Report";
|
|
2474
|
+
} else {
|
|
2475
|
+
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
function processDC(decodeResult, data) {
|
|
2479
|
+
decodeResult.raw.message_date = data[0];
|
|
2480
|
+
if (data.length === 1) {
|
|
2481
|
+
} else if (data.length === 2) {
|
|
2482
|
+
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2483
|
+
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2484
|
+
decodeResult.raw.message_timestamp = time;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
function processPS(decodeResult, data) {
|
|
2488
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2489
|
+
if (position) {
|
|
2490
|
+
decodeResult.raw.position = position;
|
|
2491
|
+
decodeResult.formatted.items.push({
|
|
2492
|
+
type: "aircraft_position",
|
|
2493
|
+
code: "POS",
|
|
2494
|
+
label: "Aircraft Position",
|
|
2495
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
2498
|
+
if (data.length === 9) {
|
|
2499
|
+
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
2500
|
+
ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
|
|
2501
|
+
ResultFormatter.temperature(decodeResult, data[6]);
|
|
2502
|
+
ResultFormatter.unknown(decodeResult, data[7]);
|
|
2503
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2504
|
+
}
|
|
2505
|
+
if (data.length === 14) {
|
|
2506
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2507
|
+
processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
|
|
2508
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2509
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2510
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2511
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2512
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2513
|
+
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
function processPosition2(decodeResult, data) {
|
|
2517
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2518
|
+
if (position) {
|
|
2519
|
+
decodeResult.raw.position = position;
|
|
2520
|
+
decodeResult.formatted.items.push({
|
|
2521
|
+
type: "aircraft_position",
|
|
2522
|
+
code: "POS",
|
|
2523
|
+
label: "Aircraft Position",
|
|
2524
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2527
|
+
if (data.length >= 10) {
|
|
2528
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2529
|
+
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
2530
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2531
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2532
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2533
|
+
}
|
|
2534
|
+
if (data.length >= 14) {
|
|
2535
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2536
|
+
ResultFormatter.unknown(decodeResult, data[11]);
|
|
2537
|
+
ResultFormatter.unknown(decodeResult, data[12]);
|
|
2538
|
+
ResultFormatter.unknown(decodeResult, data[13]);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2542
|
+
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2543
|
+
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2544
|
+
const timeFormat = date ? "epoch" : "tod";
|
|
2545
|
+
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2546
|
+
lastWaypoint.time = lastTime;
|
|
2547
|
+
lastWaypoint.timeFormat = timeFormat;
|
|
2548
|
+
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2549
|
+
nextWaypoint.time = nextTime;
|
|
2550
|
+
nextWaypoint.timeFormat = timeFormat;
|
|
2551
|
+
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2552
|
+
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2553
|
+
decodeResult.raw.route = { waypoints };
|
|
2554
|
+
decodeResult.formatted.items.push({
|
|
2555
|
+
type: "aircraft_route",
|
|
2556
|
+
code: "ROUTE",
|
|
2557
|
+
label: "Aircraft Route",
|
|
2558
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
// lib/plugins/Label_4J_POS.ts
|
|
2563
|
+
var Label_4J_POS = class extends DecoderPlugin {
|
|
2564
|
+
name = "label-4j-pos";
|
|
2565
|
+
qualifiers() {
|
|
2566
|
+
return {
|
|
2567
|
+
labels: ["4J"],
|
|
2568
|
+
preambles: ["POS/"]
|
|
2475
2569
|
};
|
|
2476
2570
|
}
|
|
2571
|
+
// copied from Label_H1.ts since i don't really want to have to have
|
|
2572
|
+
// something named like that decode more than 1 type
|
|
2573
|
+
// if we figure out a good name, i'll combine them
|
|
2477
2574
|
decode(message, options = {}) {
|
|
2478
|
-
|
|
2575
|
+
let decodeResult = this.defaultResult();
|
|
2479
2576
|
decodeResult.decoder.name = this.name;
|
|
2480
|
-
decodeResult.formatted.description = "CPDLC Message";
|
|
2481
2577
|
decodeResult.message = message;
|
|
2482
|
-
|
|
2483
|
-
|
|
2578
|
+
const msg = message.text.replace(/\n|\r/g, "");
|
|
2579
|
+
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2580
|
+
decodeResult.decoded = decoded;
|
|
2581
|
+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2582
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2583
|
+
if (options.debug) {
|
|
2584
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2585
|
+
}
|
|
2586
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2587
|
+
decodeResult.decoded = false;
|
|
2588
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2484
2589
|
}
|
|
2485
2590
|
return decodeResult;
|
|
2486
2591
|
}
|
|
2487
2592
|
};
|
|
2488
2593
|
|
|
2489
|
-
// lib/plugins/
|
|
2490
|
-
var
|
|
2491
|
-
name = "label-
|
|
2594
|
+
// lib/plugins/Label_4N.ts
|
|
2595
|
+
var Label_4N = class extends DecoderPlugin {
|
|
2596
|
+
name = "label-4n";
|
|
2492
2597
|
qualifiers() {
|
|
2493
2598
|
return {
|
|
2494
|
-
labels: ["
|
|
2599
|
+
labels: ["4N"]
|
|
2495
2600
|
};
|
|
2496
2601
|
}
|
|
2497
2602
|
decode(message, options = {}) {
|
|
2498
2603
|
const decodeResult = this.defaultResult();
|
|
2499
2604
|
decodeResult.decoder.name = this.name;
|
|
2500
|
-
decodeResult.
|
|
2501
|
-
decodeResult.formatted.description = "
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
});
|
|
2605
|
+
decodeResult.message = message;
|
|
2606
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2607
|
+
let text = message.text;
|
|
2608
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2609
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2610
|
+
text = text.substring(10);
|
|
2611
|
+
}
|
|
2508
2612
|
decodeResult.decoded = true;
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
* @param data - original message split by ':'
|
|
2523
|
-
* @returns whether all fields were processed or not
|
|
2524
|
-
*/
|
|
2525
|
-
static processFlightPlan(decodeResult, data) {
|
|
2526
|
-
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2527
|
-
for (let i = 1; i < data.length; i += 2) {
|
|
2528
|
-
const key = data[i];
|
|
2529
|
-
const value = data[i + 1];
|
|
2530
|
-
switch (key) {
|
|
2531
|
-
case "A":
|
|
2532
|
-
addProcedure(decodeResult, value, "arrival");
|
|
2533
|
-
break;
|
|
2534
|
-
case "AA":
|
|
2535
|
-
addArrivalAirport(decodeResult, value);
|
|
2536
|
-
break;
|
|
2537
|
-
case "AP":
|
|
2538
|
-
addProcedure(decodeResult, value, "approach");
|
|
2539
|
-
break;
|
|
2540
|
-
case "CR":
|
|
2541
|
-
addCompanyRoute(decodeResult, value);
|
|
2542
|
-
break;
|
|
2543
|
-
case "D":
|
|
2544
|
-
addProcedure(decodeResult, value, "departure");
|
|
2545
|
-
break;
|
|
2546
|
-
case "DA":
|
|
2547
|
-
addDepartureAirport(decodeResult, value);
|
|
2548
|
-
break;
|
|
2549
|
-
case "F":
|
|
2550
|
-
addRoute(decodeResult, value);
|
|
2551
|
-
break;
|
|
2552
|
-
case "R":
|
|
2553
|
-
addRunway(decodeResult, value);
|
|
2554
|
-
break;
|
|
2555
|
-
// case 'WS': // something about routes, has altitude, so current parsing won't work
|
|
2556
|
-
// break;
|
|
2557
|
-
default:
|
|
2558
|
-
if (allKnownFields) {
|
|
2559
|
-
decodeResult.remaining.text = "";
|
|
2560
|
-
allKnownFields = false;
|
|
2561
|
-
}
|
|
2562
|
-
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2563
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2613
|
+
const fields = text.split(",");
|
|
2614
|
+
if (text.length === 51) {
|
|
2615
|
+
decodeResult.raw.day_of_month = text.substring(0, 2);
|
|
2616
|
+
ResultFormatter.departureAirport(decodeResult, text.substring(8, 11));
|
|
2617
|
+
ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16));
|
|
2618
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(30, 45).replace(/^(.)0/, "$1")));
|
|
2619
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
|
|
2620
|
+
ResultFormatter.unknownArr(decodeResult, [text.substring(2, 4), text.substring(19, 29)], " ");
|
|
2621
|
+
} else if (fields.length === 33) {
|
|
2622
|
+
decodeResult.raw.date = fields[3];
|
|
2623
|
+
if (fields[1] === "B") {
|
|
2624
|
+
ResultFormatter.position(decodeResult, { latitude: Number(fields[4]), longitude: Number(fields[5]) });
|
|
2625
|
+
ResultFormatter.altitude(decodeResult, Number(fields[6]));
|
|
2564
2626
|
}
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
decodeResult.formatted.items.push({
|
|
2572
|
-
type: "status",
|
|
2573
|
-
code: "ROUTE_STATUS",
|
|
2574
|
-
label: "Route Status",
|
|
2575
|
-
value: "Route Filed"
|
|
2576
|
-
});
|
|
2577
|
-
decodeResult.raw.route_status = "RF";
|
|
2578
|
-
if (header.length > 2) {
|
|
2579
|
-
addRoute(decodeResult, header.substring(2));
|
|
2627
|
+
ResultFormatter.departureAirport(decodeResult, fields[8]);
|
|
2628
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[9]);
|
|
2629
|
+
ResultFormatter.alternateAirport(decodeResult, fields[10]);
|
|
2630
|
+
ResultFormatter.arrivalRunway(decodeResult, fields[11].split("/")[0]);
|
|
2631
|
+
if (fields[12].length > 1) {
|
|
2632
|
+
ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
|
|
2580
2633
|
}
|
|
2581
|
-
|
|
2582
|
-
decodeResult.
|
|
2583
|
-
decodeResult.formatted.items.push({
|
|
2584
|
-
type: "status",
|
|
2585
|
-
code: "ROUTE_STATUS",
|
|
2586
|
-
label: "Route Status",
|
|
2587
|
-
value: "Route Planned"
|
|
2588
|
-
});
|
|
2589
|
-
decodeResult.raw.route_status = header;
|
|
2590
|
-
} else if (header.startsWith("RI")) {
|
|
2591
|
-
decodeResult.raw.route_status = "RI";
|
|
2592
|
-
decodeResult.formatted.items.push({
|
|
2593
|
-
type: "status",
|
|
2594
|
-
code: "ROUTE_STATUS",
|
|
2595
|
-
label: "Route Status",
|
|
2596
|
-
value: "Route Inactive"
|
|
2597
|
-
});
|
|
2634
|
+
ResultFormatter.checksum(decodeResult, fields[32]);
|
|
2635
|
+
ResultFormatter.unknownArr(decodeResult, [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter((f) => f != ""));
|
|
2598
2636
|
} else {
|
|
2599
|
-
decodeResult.
|
|
2600
|
-
|
|
2601
|
-
}
|
|
2602
|
-
return allKnownFields;
|
|
2603
|
-
}
|
|
2604
|
-
};
|
|
2605
|
-
function addArrivalAirport(decodeResult, value) {
|
|
2606
|
-
ResultFormatter.arrivalAirport(decodeResult, value);
|
|
2607
|
-
}
|
|
2608
|
-
function addDepartureAirport(decodeResult, value) {
|
|
2609
|
-
ResultFormatter.departureAirport(decodeResult, value);
|
|
2610
|
-
}
|
|
2611
|
-
function addRunway(decodeResult, value) {
|
|
2612
|
-
if (value.length === 8) {
|
|
2613
|
-
ResultFormatter.arrivalRunway(decodeResult, value.substring(4, 7));
|
|
2614
|
-
}
|
|
2615
|
-
ResultFormatter.departureRunway(decodeResult, value.substring(0, 3));
|
|
2616
|
-
}
|
|
2617
|
-
function addRoute(decodeResult, value) {
|
|
2618
|
-
const route = value.split(".");
|
|
2619
|
-
ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
|
|
2620
|
-
}
|
|
2621
|
-
function addProcedure(decodeResult, value, type) {
|
|
2622
|
-
if (decodeResult.raw.procedures === void 0) {
|
|
2623
|
-
decodeResult.raw.procedures = [];
|
|
2624
|
-
}
|
|
2625
|
-
const data = value.split(".");
|
|
2626
|
-
let waypoints;
|
|
2627
|
-
if (data.length > 1) {
|
|
2628
|
-
waypoints = data.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
|
|
2629
|
-
}
|
|
2630
|
-
const route = { name: data[0], waypoints };
|
|
2631
|
-
decodeResult.raw.procedures.push({ type, route });
|
|
2632
|
-
const procedureName = type.substring(0, 1).toUpperCase() + type.slice(1);
|
|
2633
|
-
let procedureValue = route.name;
|
|
2634
|
-
decodeResult.formatted.items.push({
|
|
2635
|
-
type: `procedure`,
|
|
2636
|
-
code: "proc",
|
|
2637
|
-
label: `${procedureName} Procedure`,
|
|
2638
|
-
value: RouteUtils.routeToString(route)
|
|
2639
|
-
});
|
|
2640
|
-
}
|
|
2641
|
-
function addCompanyRoute(decodeResult, value) {
|
|
2642
|
-
const segments = value.split(".");
|
|
2643
|
-
const parens_idx = segments[0].indexOf("(");
|
|
2644
|
-
let name;
|
|
2645
|
-
let runway;
|
|
2646
|
-
if (parens_idx === -1) {
|
|
2647
|
-
name = segments[0];
|
|
2648
|
-
} else {
|
|
2649
|
-
name = segments[0].slice(0, parens_idx);
|
|
2650
|
-
runway = segments[0].slice(parens_idx + 1, segments[0].indexOf(")"));
|
|
2651
|
-
}
|
|
2652
|
-
let waypoints;
|
|
2653
|
-
if (segments.length > 1) {
|
|
2654
|
-
waypoints = segments.slice(1).map((leg) => RouteUtils.getWaypoint(leg));
|
|
2655
|
-
}
|
|
2656
|
-
decodeResult.raw.company_route = {
|
|
2657
|
-
name,
|
|
2658
|
-
runway,
|
|
2659
|
-
waypoints
|
|
2660
|
-
};
|
|
2661
|
-
decodeResult.formatted.items.push({
|
|
2662
|
-
type: "company_route",
|
|
2663
|
-
code: "CR",
|
|
2664
|
-
label: "Company Route",
|
|
2665
|
-
value: RouteUtils.routeToString(decodeResult.raw.company_route)
|
|
2666
|
-
});
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
// lib/utils/h1_helper.ts
|
|
2670
|
-
var H1Helper = class {
|
|
2671
|
-
static decodeH1Message(decodeResult, message) {
|
|
2672
|
-
const checksum = message.slice(-4);
|
|
2673
|
-
const data = message.slice(0, message.length - 4);
|
|
2674
|
-
const fields = data.split("/");
|
|
2675
|
-
parseMessageType(decodeResult, fields[0]);
|
|
2676
|
-
for (let i = 1; i < fields.length; ++i) {
|
|
2677
|
-
if (fields[i].startsWith("FN")) {
|
|
2678
|
-
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2679
|
-
} else if (fields[i].startsWith("SN")) {
|
|
2680
|
-
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2681
|
-
} else if (fields[i].startsWith("DC")) {
|
|
2682
|
-
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2683
|
-
} else if (fields[i].startsWith("TS")) {
|
|
2684
|
-
const ts = fields[i].substring(2).split(",");
|
|
2685
|
-
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2686
|
-
if (Number.isNaN(time)) {
|
|
2687
|
-
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2688
|
-
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2689
|
-
}
|
|
2690
|
-
decodeResult.raw.message_date = ts[1];
|
|
2691
|
-
decodeResult.raw.message_timestamp = time;
|
|
2692
|
-
} else if (fields[i].startsWith("PS")) {
|
|
2693
|
-
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2694
|
-
} else if (fields[i].startsWith("DT")) {
|
|
2695
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2696
|
-
processDT(decodeResult, data2);
|
|
2697
|
-
} else if (fields[i].startsWith("ID")) {
|
|
2698
|
-
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2699
|
-
} else if (fields[i].startsWith("LR")) {
|
|
2700
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2701
|
-
processLR(decodeResult, data2);
|
|
2702
|
-
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2703
|
-
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2704
|
-
} else if (fields[i].startsWith("PR")) {
|
|
2705
|
-
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2706
|
-
} else if (fields[i].startsWith("AF")) {
|
|
2707
|
-
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2708
|
-
} else if (fields[i].startsWith("TD")) {
|
|
2709
|
-
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2710
|
-
} else if (fields[i].startsWith("FX")) {
|
|
2711
|
-
ResultFormatter.freetext(decodeResult, fields[i].substring(2));
|
|
2712
|
-
} else if (fields[i].startsWith("ET")) {
|
|
2713
|
-
if (fields[i].length === 7) {
|
|
2714
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3) + "00"));
|
|
2715
|
-
} else if (fields[i].length === 8) {
|
|
2716
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4) + "00"));
|
|
2717
|
-
} else {
|
|
2718
|
-
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2719
|
-
}
|
|
2720
|
-
} else {
|
|
2721
|
-
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2722
|
-
}
|
|
2637
|
+
decodeResult.decoded = false;
|
|
2638
|
+
ResultFormatter.unknown(decodeResult, text);
|
|
2723
2639
|
}
|
|
2724
|
-
if (decodeResult.
|
|
2725
|
-
|
|
2640
|
+
if (decodeResult.decoded) {
|
|
2641
|
+
if (!decodeResult.remaining.text)
|
|
2642
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2643
|
+
else
|
|
2644
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2645
|
+
} else {
|
|
2646
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2726
2647
|
}
|
|
2727
|
-
return
|
|
2648
|
+
return decodeResult;
|
|
2728
2649
|
}
|
|
2729
2650
|
};
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
}
|
|
2754
|
-
} else {
|
|
2755
|
-
ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
|
-
function processIdentification(decodeResult, data) {
|
|
2759
|
-
ResultFormatter.tail(decodeResult, data[0]);
|
|
2760
|
-
if (data.length > 1) {
|
|
2761
|
-
decodeResult.raw.flight_number = data[1];
|
|
2762
|
-
}
|
|
2763
|
-
if (data.length > 2) {
|
|
2764
|
-
decodeResult.raw.mission_number = data[2];
|
|
2765
|
-
}
|
|
2766
|
-
}
|
|
2767
|
-
function processDT(decodeResult, data) {
|
|
2768
|
-
if (!decodeResult.raw.arrival_icao) {
|
|
2769
|
-
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2770
|
-
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2771
|
-
ResultFormatter.unknownArr(decodeResult, data);
|
|
2772
|
-
}
|
|
2773
|
-
if (data.length > 1) {
|
|
2774
|
-
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2775
|
-
}
|
|
2776
|
-
if (data.length > 2) {
|
|
2777
|
-
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2778
|
-
}
|
|
2779
|
-
if (data.length > 3) {
|
|
2780
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2781
|
-
}
|
|
2782
|
-
if (data.length > 4) {
|
|
2783
|
-
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2784
|
-
}
|
|
2785
|
-
if (data.length > 5) {
|
|
2786
|
-
ResultFormatter.unknownArr(decodeResult, data);
|
|
2651
|
+
|
|
2652
|
+
// lib/plugins/Label_80.ts
|
|
2653
|
+
var Label_80 = class extends DecoderPlugin {
|
|
2654
|
+
name = "label-80";
|
|
2655
|
+
descriptions = {
|
|
2656
|
+
ALT: "Altitude",
|
|
2657
|
+
DWND: "Wind Direction",
|
|
2658
|
+
ETA: "Estimated Time of Arrival",
|
|
2659
|
+
FOB: "Fuel on Board",
|
|
2660
|
+
FL: "Flight Level",
|
|
2661
|
+
HDG: "Heading",
|
|
2662
|
+
MCH: "Aircraft Speed",
|
|
2663
|
+
NWYP: "Next Waypoint",
|
|
2664
|
+
POS: "Aircraft Position",
|
|
2665
|
+
SAT: "Static Air Temperature",
|
|
2666
|
+
SWND: "Wind Speed",
|
|
2667
|
+
TAS: "True Airspeed",
|
|
2668
|
+
WYP: "Waypoint"
|
|
2669
|
+
};
|
|
2670
|
+
qualifiers() {
|
|
2671
|
+
return {
|
|
2672
|
+
labels: ["80"],
|
|
2673
|
+
preambles: ["3N01 POSRPT"]
|
|
2674
|
+
};
|
|
2787
2675
|
}
|
|
2788
|
-
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2676
|
+
decode(message, options = {}) {
|
|
2677
|
+
const decodeResult = this.defaultResult();
|
|
2678
|
+
decodeResult.decoder.name = this.name;
|
|
2679
|
+
decodeResult.formatted.description = "Airline Defined Position Report";
|
|
2680
|
+
const parts = message.text.split("\n");
|
|
2681
|
+
let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
|
|
2682
|
+
let results = parts[0].match(posRptRegex);
|
|
2683
|
+
if (!results?.groups) {
|
|
2684
|
+
decodeResult.decoded = false;
|
|
2685
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2686
|
+
return decodeResult;
|
|
2687
|
+
}
|
|
2688
|
+
if (results && results.length > 0) {
|
|
2689
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
2690
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
2691
|
+
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
2692
|
+
if (results.groups.agate) {
|
|
2693
|
+
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
2694
|
+
decodeResult.formatted.items.push({
|
|
2695
|
+
type: "arrival_gate",
|
|
2696
|
+
code: "ARG",
|
|
2697
|
+
label: "Arrival Gate",
|
|
2698
|
+
value: `${results.groups.agate}`
|
|
2699
|
+
});
|
|
2700
|
+
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
2701
|
+
decodeResult.formatted.items.push({
|
|
2702
|
+
type: "scheduled_time_of_arrival",
|
|
2703
|
+
code: "STA",
|
|
2704
|
+
label: "Scheduled Time of Arrival",
|
|
2705
|
+
value: `${results.groups.sta}`
|
|
2706
|
+
});
|
|
2707
|
+
}
|
|
2708
|
+
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
2709
|
+
const remainingParts = parts.slice(1);
|
|
2710
|
+
for (const part of remainingParts) {
|
|
2711
|
+
const matches = part.matchAll(posRptRegex);
|
|
2712
|
+
for (const match of matches) {
|
|
2713
|
+
switch (match.groups?.field) {
|
|
2714
|
+
case "ALT": {
|
|
2715
|
+
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
2716
|
+
break;
|
|
2717
|
+
}
|
|
2718
|
+
case "DWND": {
|
|
2719
|
+
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
2720
|
+
decodeResult.formatted.items.push({
|
|
2721
|
+
type: "wind_direction",
|
|
2722
|
+
code: "DWND",
|
|
2723
|
+
label: this.descriptions[match.groups.field],
|
|
2724
|
+
value: decodeResult.raw.wind_direction
|
|
2725
|
+
});
|
|
2726
|
+
break;
|
|
2727
|
+
}
|
|
2728
|
+
case "FL": {
|
|
2729
|
+
const flight_level = Number(match.groups.value);
|
|
2730
|
+
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
2731
|
+
break;
|
|
2732
|
+
}
|
|
2733
|
+
case "FOB": {
|
|
2734
|
+
const fob = Number(match.groups.value);
|
|
2735
|
+
if (!isNaN(fob)) {
|
|
2736
|
+
ResultFormatter.currentFuel(decodeResult, fob);
|
|
2737
|
+
}
|
|
2738
|
+
break;
|
|
2739
|
+
}
|
|
2740
|
+
case "HDG": {
|
|
2741
|
+
ResultFormatter.heading(decodeResult, Number(match.groups.value));
|
|
2742
|
+
break;
|
|
2743
|
+
}
|
|
2744
|
+
case "MCH": {
|
|
2745
|
+
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2746
|
+
decodeResult.formatted.items.push({
|
|
2747
|
+
type: "mach",
|
|
2748
|
+
code: "MCH",
|
|
2749
|
+
label: this.descriptions[match.groups.field],
|
|
2750
|
+
value: `${decodeResult.raw.mach} Mach`
|
|
2751
|
+
});
|
|
2752
|
+
break;
|
|
2753
|
+
}
|
|
2754
|
+
case "NWYP": {
|
|
2755
|
+
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2756
|
+
decodeResult.formatted.items.push({
|
|
2757
|
+
type: "next_waypoint",
|
|
2758
|
+
code: "NWYP",
|
|
2759
|
+
label: this.descriptions[match.groups.field],
|
|
2760
|
+
value: decodeResult.raw.next_waypoint
|
|
2761
|
+
});
|
|
2762
|
+
break;
|
|
2763
|
+
}
|
|
2764
|
+
case "POS": {
|
|
2765
|
+
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2766
|
+
const posResult = match.groups.value.match(posRegex);
|
|
2767
|
+
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2768
|
+
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2769
|
+
const position = {
|
|
2770
|
+
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2771
|
+
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2772
|
+
};
|
|
2773
|
+
ResultFormatter.position(decodeResult, position);
|
|
2774
|
+
break;
|
|
2775
|
+
}
|
|
2776
|
+
case "SWND": {
|
|
2777
|
+
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2778
|
+
decodeResult.formatted.items.push({
|
|
2779
|
+
type: "wind_speed",
|
|
2780
|
+
code: "SWND",
|
|
2781
|
+
label: this.descriptions[match.groups.field],
|
|
2782
|
+
value: decodeResult.raw.wind_speed
|
|
2783
|
+
});
|
|
2784
|
+
break;
|
|
2785
|
+
}
|
|
2786
|
+
default: {
|
|
2787
|
+
if (match.groups?.field != void 0) {
|
|
2788
|
+
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2789
|
+
decodeResult.formatted.items.push({
|
|
2790
|
+
type: match.groups.field,
|
|
2791
|
+
code: match.groups.field,
|
|
2792
|
+
label: description || `Unknown (${match.groups.field})`,
|
|
2793
|
+
value: `${match.groups.value}`
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
decodeResult.decoded = true;
|
|
2801
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2802
|
+
}
|
|
2803
|
+
return decodeResult;
|
|
2799
2804
|
}
|
|
2800
|
-
}
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2805
|
+
};
|
|
2806
|
+
|
|
2807
|
+
// lib/plugins/Label_83.ts
|
|
2808
|
+
var Label_83 = class extends DecoderPlugin {
|
|
2809
|
+
name = "label-83";
|
|
2810
|
+
qualifiers() {
|
|
2811
|
+
return {
|
|
2812
|
+
labels: ["83"]
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
decode(message, options = {}) {
|
|
2816
|
+
const decodeResult = this.defaultResult();
|
|
2817
|
+
decodeResult.decoder.name = this.name;
|
|
2818
|
+
decodeResult.message = message;
|
|
2819
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2820
|
+
let text = message.text;
|
|
2821
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2822
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2823
|
+
text = text.substring(10);
|
|
2807
2824
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2825
|
+
decodeResult.decoded = true;
|
|
2826
|
+
if (text.substring(0, 10) === "4DH3 ETAT2") {
|
|
2827
|
+
const fields = text.split(/\s+/);
|
|
2828
|
+
if (fields[2].length > 5) {
|
|
2829
|
+
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
2830
|
+
}
|
|
2831
|
+
ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
|
|
2832
|
+
const subfields = fields[3].split("/");
|
|
2833
|
+
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
2834
|
+
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
2835
|
+
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
2836
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2837
|
+
} else if (text.substring(0, 5) === "001PR") {
|
|
2838
|
+
decodeResult.raw.day_of_month = text.substring(5, 7);
|
|
2839
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(13, 28).replace(/\./g, ""));
|
|
2840
|
+
if (position) {
|
|
2841
|
+
ResultFormatter.position(decodeResult, position);
|
|
2842
|
+
}
|
|
2843
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
|
|
2844
|
+
ResultFormatter.unknown(decodeResult, text.substring(33));
|
|
2845
|
+
} else {
|
|
2846
|
+
const fields = text.replace(/\s/g, "").split(",");
|
|
2847
|
+
if (fields.length === 9) {
|
|
2848
|
+
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
2849
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
2850
|
+
decodeResult.raw.day_of_month = fields[2].substring(0, 2);
|
|
2851
|
+
decodeResult.raw.time = fields[2].substring(2);
|
|
2852
|
+
ResultFormatter.position(
|
|
2853
|
+
decodeResult,
|
|
2854
|
+
{
|
|
2855
|
+
latitude: Number(fields[3].replace(/\s/g, "")),
|
|
2856
|
+
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
2857
|
+
}
|
|
2858
|
+
);
|
|
2859
|
+
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
2860
|
+
ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
|
|
2861
|
+
ResultFormatter.heading(decodeResult, Number(fields[7]));
|
|
2862
|
+
ResultFormatter.unknown(decodeResult, fields[8]);
|
|
2863
|
+
} else {
|
|
2864
|
+
decodeResult.decoded = false;
|
|
2865
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2866
|
+
}
|
|
2814
2867
|
}
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2868
|
+
if (decodeResult.decoded) {
|
|
2869
|
+
if (!decodeResult.remaining.text)
|
|
2870
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2871
|
+
else
|
|
2872
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2873
|
+
} else {
|
|
2874
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2818
2875
|
}
|
|
2819
|
-
|
|
2820
|
-
} else {
|
|
2821
|
-
ResultFormatter.unknown(decodeResult, messageType);
|
|
2876
|
+
return decodeResult;
|
|
2822
2877
|
}
|
|
2823
|
-
}
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
decodeResult.formatted.description = "Position Report";
|
|
2833
|
-
} else if (type === "PRG") {
|
|
2834
|
-
decodeResult.formatted.description = "Progress Report";
|
|
2835
|
-
} else {
|
|
2836
|
-
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2878
|
+
};
|
|
2879
|
+
|
|
2880
|
+
// lib/plugins/Label_8E.ts
|
|
2881
|
+
var Label_8E = class extends DecoderPlugin {
|
|
2882
|
+
name = "label-8e";
|
|
2883
|
+
qualifiers() {
|
|
2884
|
+
return {
|
|
2885
|
+
labels: ["8E"]
|
|
2886
|
+
};
|
|
2837
2887
|
}
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
const
|
|
2844
|
-
const
|
|
2845
|
-
|
|
2888
|
+
decode(message, options = {}) {
|
|
2889
|
+
const decodeResult = this.defaultResult();
|
|
2890
|
+
decodeResult.decoder.name = this.name;
|
|
2891
|
+
decodeResult.formatted.description = "ETA Report";
|
|
2892
|
+
decodeResult.message = message;
|
|
2893
|
+
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2894
|
+
const results = message.text.match(regex);
|
|
2895
|
+
if (results?.groups) {
|
|
2896
|
+
if (options.debug) {
|
|
2897
|
+
console.log(`Label 8E ETA: groups`);
|
|
2898
|
+
console.log(results.groups);
|
|
2899
|
+
}
|
|
2900
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2901
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2902
|
+
}
|
|
2903
|
+
decodeResult.decoded = true;
|
|
2904
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2905
|
+
return decodeResult;
|
|
2846
2906
|
}
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
});
|
|
2907
|
+
};
|
|
2908
|
+
|
|
2909
|
+
// lib/plugins/Label_B6.ts
|
|
2910
|
+
var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
2911
|
+
name = "label-b6-forwardslash";
|
|
2912
|
+
qualifiers() {
|
|
2913
|
+
return {
|
|
2914
|
+
labels: ["B6"],
|
|
2915
|
+
preambles: ["/"]
|
|
2916
|
+
};
|
|
2858
2917
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2918
|
+
decode(message, options = {}) {
|
|
2919
|
+
const decodeResult = this.defaultResult();
|
|
2920
|
+
decodeResult.decoder.name = this.name;
|
|
2921
|
+
decodeResult.formatted.description = "CPDLC Message";
|
|
2922
|
+
decodeResult.message = message;
|
|
2923
|
+
if (options.debug) {
|
|
2924
|
+
console.log("CPDLC: " + message);
|
|
2925
|
+
}
|
|
2926
|
+
return decodeResult;
|
|
2865
2927
|
}
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2928
|
+
};
|
|
2929
|
+
|
|
2930
|
+
// lib/plugins/Label_ColonComma.ts
|
|
2931
|
+
var Label_ColonComma = class extends DecoderPlugin {
|
|
2932
|
+
name = "label-colon-comma";
|
|
2933
|
+
qualifiers() {
|
|
2934
|
+
return {
|
|
2935
|
+
labels: [":;"]
|
|
2936
|
+
};
|
|
2875
2937
|
}
|
|
2876
|
-
}
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
decodeResult.
|
|
2938
|
+
decode(message, options = {}) {
|
|
2939
|
+
const decodeResult = this.defaultResult();
|
|
2940
|
+
decodeResult.decoder.name = this.name;
|
|
2941
|
+
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
2942
|
+
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
2881
2943
|
decodeResult.formatted.items.push({
|
|
2882
|
-
type: "
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2944
|
+
type: "frequency",
|
|
2945
|
+
label: "Frequency",
|
|
2946
|
+
value: `${decodeResult.raw.frequency} MHz`,
|
|
2947
|
+
code: "FREQ"
|
|
2886
2948
|
});
|
|
2949
|
+
decodeResult.decoded = true;
|
|
2950
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2951
|
+
return decodeResult;
|
|
2887
2952
|
}
|
|
2888
|
-
|
|
2889
|
-
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2890
|
-
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
2891
|
-
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2892
|
-
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2893
|
-
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2894
|
-
}
|
|
2895
|
-
if (data.length >= 14) {
|
|
2896
|
-
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2897
|
-
ResultFormatter.unknown(decodeResult, data[11]);
|
|
2898
|
-
ResultFormatter.unknown(decodeResult, data[12]);
|
|
2899
|
-
ResultFormatter.unknown(decodeResult, data[13]);
|
|
2900
|
-
}
|
|
2901
|
-
}
|
|
2902
|
-
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2903
|
-
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2904
|
-
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2905
|
-
const timeFormat = date ? "epoch" : "tod";
|
|
2906
|
-
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2907
|
-
lastWaypoint.time = lastTime;
|
|
2908
|
-
lastWaypoint.timeFormat = timeFormat;
|
|
2909
|
-
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2910
|
-
nextWaypoint.time = nextTime;
|
|
2911
|
-
nextWaypoint.timeFormat = timeFormat;
|
|
2912
|
-
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2913
|
-
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2914
|
-
decodeResult.raw.route = { waypoints };
|
|
2915
|
-
decodeResult.formatted.items.push({
|
|
2916
|
-
type: "aircraft_route",
|
|
2917
|
-
code: "ROUTE",
|
|
2918
|
-
label: "Aircraft Route",
|
|
2919
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2920
|
-
});
|
|
2921
|
-
}
|
|
2953
|
+
};
|
|
2922
2954
|
|
|
2923
2955
|
// lib/plugins/Label_H1.ts
|
|
2924
2956
|
var Label_H1 = class extends DecoderPlugin {
|
|
@@ -4257,6 +4289,7 @@ var MessageDecoder = class {
|
|
|
4257
4289
|
this.registerPlugin(new Label_4A_DIS(this));
|
|
4258
4290
|
this.registerPlugin(new Label_4A_DOOR(this));
|
|
4259
4291
|
this.registerPlugin(new Label_4A_Slash_01(this));
|
|
4292
|
+
this.registerPlugin(new Label_4J_POS(this));
|
|
4260
4293
|
this.registerPlugin(new Label_4N(this));
|
|
4261
4294
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
4262
4295
|
this.registerPlugin(new Label_H1_FLR(this));
|