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