@airframes/acars-decoder 1.6.2 → 1.6.4

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.mjs CHANGED
@@ -167,6 +167,32 @@ var Label_5Z = class extends DecoderPlugin {
167
167
  }
168
168
  };
169
169
 
170
+ // lib/utils/coordinate_utils.ts
171
+ var CoordinateUtils = class {
172
+ static decodeStringCoordinates(stringCoords) {
173
+ var results = {};
174
+ const firstChar = stringCoords.substring(0, 1);
175
+ let middleChar = stringCoords.substring(6, 7);
176
+ let longitudeChars = stringCoords.substring(7, 13);
177
+ if (middleChar == " ") {
178
+ middleChar = stringCoords.substring(7, 8);
179
+ longitudeChars = stringCoords.substring(8, 14);
180
+ }
181
+ if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
182
+ results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar === "S" ? -1 : 1);
183
+ results.longitude = Number(longitudeChars) / 1e3 * (middleChar === "W" ? -1 : 1);
184
+ } else {
185
+ return;
186
+ }
187
+ return results;
188
+ }
189
+ static coordinateString(coords) {
190
+ const latDir = coords.latitude > 0 ? "N" : "S";
191
+ const lonDir = coords.longitude > 0 ? "E" : "W";
192
+ return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
193
+ }
194
+ };
195
+
170
196
  // lib/plugins/Label_12_N_Space.ts
171
197
  var Label_12_N_Space = class extends DecoderPlugin {
172
198
  name = "label-12-n-space";
@@ -188,16 +214,16 @@ var Label_12_N_Space = class extends DecoderPlugin {
188
214
  console.log(`Label 12 N : results`);
189
215
  console.log(results);
190
216
  }
191
- decodeResult.raw.latitude_direction = results.groups.lat;
192
- decodeResult.raw.latitude = Number(results.groups.lat_coord);
193
- decodeResult.raw.longitude_direction = results.groups.long;
194
- decodeResult.raw.longitude = Number(results.groups.long_coord);
217
+ decodeResult.raw.position = {
218
+ latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
219
+ longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
220
+ };
195
221
  decodeResult.raw.flight_level = results.groups.alt == "GRD" || results.groups.alt == "***" ? "0" : Number(results.groups.alt);
196
222
  decodeResult.formatted.items.push({
197
223
  type: "aircraft_position",
198
224
  code: "POS",
199
225
  label: "Aircraft Position",
200
- value: `${results.groups.lat_coord} ${decodeResult.raw.latitude_direction}, ${results.groups.long_coord} ${decodeResult.raw.longitude_direction}`
226
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
201
227
  });
202
228
  decodeResult.formatted.items.push({
203
229
  type: "flight_level",
@@ -220,37 +246,6 @@ var Label_12_N_Space = class extends DecoderPlugin {
220
246
  }
221
247
  };
222
248
 
223
- // lib/utils/coordinate_utils.ts
224
- var CoordinateUtils = class {
225
- static decodeStringCoordinates(stringCoords) {
226
- var results = {};
227
- const firstChar = stringCoords.substring(0, 1);
228
- let middleChar = stringCoords.substring(6, 7);
229
- let longitudeChars = stringCoords.substring(7, 13);
230
- if (middleChar == " ") {
231
- middleChar = stringCoords.substring(7, 8);
232
- longitudeChars = stringCoords.substring(8, 14);
233
- }
234
- if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
235
- results.latitudeDirection = firstChar;
236
- results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar === "S" ? -1 : 1);
237
- results.longitudeDirection = middleChar;
238
- results.longitude = Number(longitudeChars) / 1e3 * (middleChar === "W" ? -1 : 1);
239
- } else {
240
- return;
241
- }
242
- return results;
243
- }
244
- static coordinateString(coords) {
245
- return `${Math.abs(coords.latitude)} ${coords.latitudeDirection}, ${Math.abs(coords.longitude)} ${coords.longitudeDirection}`;
246
- }
247
- static latLonToCoordinateString(lat, lon) {
248
- const latDir = lat > 0 ? "N" : "S";
249
- const lonDir = lon > 0 ? "E" : "W";
250
- return `${Math.abs(lat)} ${latDir}, ${Math.abs(lon)} ${lonDir}`;
251
- }
252
- };
253
-
254
249
  // lib/plugins/Label_15.ts
255
250
  var Label_15 = class extends DecoderPlugin {
256
251
  name = "label-5z";
@@ -304,9 +299,7 @@ var Label_15_FST = class extends DecoderPlugin {
304
299
  const middleChar = stringCoords.substring(7, 8);
305
300
  decodeResult.raw.position = {};
306
301
  if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
307
- decodeResult.raw.position.latitudeDirection = firstChar;
308
302
  decodeResult.raw.position.latitude = Number(stringCoords.substring(1, 7)) / 1e4 * (firstChar === "S" ? -1 : 1);
309
- decodeResult.raw.position.longitudeDirection = middleChar;
310
303
  decodeResult.raw.position.longitude = Number(stringCoords.substring(8, 26)) / 1e5 * (middleChar === "W" ? -1 : 1);
311
304
  } else {
312
305
  decodeResult.decoded = false;
@@ -358,16 +351,16 @@ var Label_16_N_Space = class extends DecoderPlugin {
358
351
  console.log(`Label 16 N : results`);
359
352
  console.log(results);
360
353
  }
361
- decodeResult.raw.latitude_direction = results.groups.lat;
362
- decodeResult.raw.latitude = Number(results.groups.lat_coord);
363
- decodeResult.raw.longitude_direction = results.groups.long;
364
- decodeResult.raw.longitude = Number(results.groups.long_coord);
354
+ decodeResult.raw.position = {
355
+ latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
356
+ longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
357
+ };
365
358
  decodeResult.raw.flight_level = results.groups.alt == "GRD" || results.groups.alt == "***" ? "0" : Number(results.groups.alt);
366
359
  decodeResult.formatted.items.push({
367
360
  type: "aircraft_position",
368
361
  code: "POS",
369
362
  label: "Aircraft Position",
370
- value: `${decodeResult.raw.latitude} ${decodeResult.raw.latitude_direction}, ${decodeResult.raw.longitude} ${decodeResult.raw.longitude_direction}`
363
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
371
364
  });
372
365
  decodeResult.formatted.items.push({
373
366
  type: "flight_level",
@@ -383,15 +376,15 @@ var Label_16_N_Space = class extends DecoderPlugin {
383
376
  console.log(`Label 16 N : results`);
384
377
  console.log(results);
385
378
  }
386
- decodeResult.raw.latitude_direction = results.groups.lat;
387
- decodeResult.raw.latitude = Number(results.groups.lat_coord);
388
- decodeResult.raw.longitude_direction = results.groups.long;
389
- decodeResult.raw.longitude = Number(results.groups.long_coord);
379
+ decodeResult.raw.position = {
380
+ latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
381
+ longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
382
+ };
390
383
  decodeResult.formatted.items.push({
391
384
  type: "aircraft_position",
392
385
  code: "POS",
393
386
  label: "Aircraft Position",
394
- value: `${results.groups.lat_coord} ${decodeResult.raw.latitude_direction}, ${results.groups.long_coord} ${decodeResult.raw.longitude_direction}`
387
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
395
388
  });
396
389
  decodeResult.decoded = true;
397
390
  decodeResult.decoder.decodeLevel = "full";
@@ -446,11 +439,14 @@ var DateTimeUtils = class {
446
439
  /**
447
440
  *
448
441
  * @param time HHMMSS
449
- * @param date MMDDYY
442
+ * @param date MMDDYY or MMDDYYYY
450
443
  * @returns seconds since epoch
451
444
  */
452
445
  static convertDateTimeToEpoch(time, date) {
453
- const timestamp = `20${date.substring(4, 6)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
446
+ if (date.length === 6) {
447
+ date = date.substring(0, 4) + `20${date.substring(4, 6)}`;
448
+ }
449
+ const timestamp = `${date.substring(4, 8)}-${date.substring(0, 2)}-${date.substring(2, 4)}T${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}.000Z`;
454
450
  const millis = Date.parse(timestamp);
455
451
  return millis / 1e3;
456
452
  }
@@ -542,11 +538,13 @@ var Label_20_POS = class extends DecoderPlugin {
542
538
  console.log(`DEBUG: ${this.name}: Variation 2 detected`);
543
539
  const rawCoords = fields[0];
544
540
  decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(rawCoords);
545
- decodeResult.formatted.items.push({
546
- type: "position",
547
- label: "Position",
548
- value: CoordinateUtils.coordinateString(decodeResult.raw.position)
549
- });
541
+ if (decodeResult.raw.position) {
542
+ decodeResult.formatted.items.push({
543
+ type: "position",
544
+ label: "Position",
545
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
546
+ });
547
+ }
550
548
  decodeResult.decoded = true;
551
549
  decodeResult.decoder.decodeLevel = "full";
552
550
  } else {
@@ -1052,7 +1050,7 @@ var Label_80 = class extends DecoderPlugin {
1052
1050
  const lon = Number(posResult.groups.lng) * (posResult.groups.lngd === "W" ? -1 : 1);
1053
1051
  const latitude = Number.isInteger(lat) ? lat / 1e3 : lat / 100;
1054
1052
  const longitude = Number.isInteger(lon) ? lon / 1e3 : lon / 100;
1055
- decodeResult.raw.aircraft_position = {
1053
+ decodeResult.raw.position = {
1056
1054
  latitude,
1057
1055
  longitude
1058
1056
  };
@@ -1060,7 +1058,7 @@ var Label_80 = class extends DecoderPlugin {
1060
1058
  type: "position",
1061
1059
  code: "POS",
1062
1060
  label: "Position",
1063
- value: `${Math.abs(latitude).toPrecision(5)} ${posResult.groups.latd}, ${Math.abs(longitude).toPrecision(5)} ${posResult.groups.lngd}`
1061
+ value: CoordinateUtils.coordinateString(decodeResult.raw.position)
1064
1062
  });
1065
1063
  break;
1066
1064
  }
@@ -1203,7 +1201,10 @@ var RouteUtils = class _RouteUtils {
1203
1201
  static waypointToString(waypoint) {
1204
1202
  let s = waypoint.name;
1205
1203
  if (waypoint.latitude && waypoint.longitude) {
1206
- s += `(${CoordinateUtils.latLonToCoordinateString(waypoint.latitude, waypoint.longitude)})`;
1204
+ s += `(${CoordinateUtils.coordinateString({ latitude: waypoint.latitude, longitude: waypoint.longitude })})`;
1205
+ }
1206
+ if (waypoint.offset) {
1207
+ s += `[${waypoint.offset.bearing}\xB0 ${waypoint.offset.distance}nm]`;
1207
1208
  }
1208
1209
  if (waypoint.time && waypoint.timeFormat) {
1209
1210
  s += `@${_RouteUtils.timestampToString(waypoint.time, waypoint.timeFormat)}`;
@@ -1211,14 +1212,23 @@ var RouteUtils = class _RouteUtils {
1211
1212
  return s;
1212
1213
  }
1213
1214
  static getWaypoint(leg) {
1215
+ const regex = leg.match(/^([A-Z]+)(\d{3})-(\d{4})$/);
1216
+ if (regex?.length == 4) {
1217
+ return { name: regex[1], offset: { bearing: parseInt(regex[2]), distance: parseInt(regex[3]) / 10 } };
1218
+ }
1214
1219
  const waypoint = leg.split(",");
1215
1220
  if (waypoint.length == 2) {
1216
1221
  const position = CoordinateUtils.decodeStringCoordinates(waypoint[1]);
1217
- return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1222
+ if (position) {
1223
+ return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1224
+ }
1218
1225
  }
1219
- if (leg.length == 14) {
1226
+ if (leg.length == 13 || leg.length == 14) {
1220
1227
  const position = CoordinateUtils.decodeStringCoordinates(leg);
1221
- return { name: waypoint[0], latitude: position.latitude, longitude: position.longitude };
1228
+ const name = waypoint.length == 2 ? waypoint[0] : "";
1229
+ if (position) {
1230
+ return { name, latitude: position.latitude, longitude: position.longitude };
1231
+ }
1222
1232
  }
1223
1233
  return { name: leg };
1224
1234
  }
@@ -1278,7 +1288,7 @@ var FlightPlanUtils = class {
1278
1288
  addRoute(decodeResult, value);
1279
1289
  break;
1280
1290
  case "R":
1281
- addDepartureRunway(decodeResult, value);
1291
+ addRunway(decodeResult, value);
1282
1292
  break;
1283
1293
  default:
1284
1294
  if (allKnownFields) {
@@ -1292,41 +1302,106 @@ var FlightPlanUtils = class {
1292
1302
  return allKnownFields;
1293
1303
  }
1294
1304
  };
1305
+ function parseMessageType(decodeResult, messageType) {
1306
+ let decoded = true;
1307
+ const parts = messageType.split("#");
1308
+ if (parts.length == 1) {
1309
+ if (parts[0].startsWith("POS") && parts[0].length !== 3 && !parts[0].startsWith("POS/")) {
1310
+ decoded = processPosition(decodeResult, parts[0].substring(3));
1311
+ }
1312
+ return decoded;
1313
+ } else if (parts.length == 2) {
1314
+ if (parts[0].length > 0) {
1315
+ decodeResult.remaining.text += parts[0].substring(0, 3);
1316
+ decodeResult.raw.flight_number = parts[0].substring(3);
1317
+ decodeResult.remaining.text += "#" + parts[1].substring(0, 3);
1318
+ }
1319
+ if (parts[1].substring(3, 6) === "POS" && parts[1].length !== 6 && parts[1].substring(3, 7) !== "POS/") {
1320
+ decoded = processPosition(decodeResult, parts[1].substring(6));
1321
+ }
1322
+ decodeResult.raw.message_type = messageType;
1323
+ return decoded;
1324
+ }
1325
+ decodeResult.remaining.text += messageType;
1326
+ return false;
1327
+ }
1295
1328
  function parseHeader(decodeResult, header) {
1296
1329
  let allKnownFields = true;
1297
1330
  const fields = header.split("/");
1298
- for (let i = 1; i < fields.length - 1; ++i) {
1331
+ allKnownFields = allKnownFields && parseMessageType(decodeResult, fields[0]);
1332
+ for (let i = 1; i < fields.length; ++i) {
1299
1333
  if (fields[i].startsWith("FN")) {
1300
1334
  decodeResult.raw.flight_number = fields[i].substring(2);
1301
1335
  } else if (fields[i].startsWith("SN")) {
1302
1336
  decodeResult.raw.serial_number = fields[i].substring(2);
1303
1337
  } else if (fields[i].startsWith("TS")) {
1304
1338
  const ts = fields[i].substring(2).split(",");
1305
- decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1339
+ let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
1340
+ if (Number.isNaN(time)) {
1341
+ const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
1342
+ time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
1343
+ }
1344
+ decodeResult.raw.message_timestamp = time;
1345
+ } else if (fields[i].startsWith("PS")) {
1346
+ const pos = fields[i].substring(2);
1347
+ allKnownFields == allKnownFields && processPosition(decodeResult, pos);
1348
+ } else if (fields[i].startsWith("DT")) {
1349
+ const icao = fields[i].substring(2);
1350
+ decodeResult.raw.arrival_icao = icao;
1351
+ decodeResult.formatted.items.push({
1352
+ type: "destination",
1353
+ code: "DST",
1354
+ label: "Destination",
1355
+ value: decodeResult.raw.arrival_icao
1356
+ });
1357
+ } else if (fields[i].startsWith("RF")) {
1358
+ decodeResult.formatted.items.push({
1359
+ type: "status",
1360
+ code: "ROUTE_STATUS",
1361
+ label: "Route Status",
1362
+ value: "Route Filed"
1363
+ });
1364
+ decodeResult.raw.route_status = "RF";
1365
+ if (fields[i].length > 2) {
1366
+ addRoute(decodeResult, fields[i].substring(2));
1367
+ }
1368
+ } else if (fields[i] == "RP") {
1369
+ decodeResult.raw.route_status = "RP";
1370
+ decodeResult.formatted.items.push({
1371
+ type: "status",
1372
+ code: "ROUTE_STATUS",
1373
+ label: "Route Status",
1374
+ value: "Route Planned"
1375
+ });
1376
+ decodeResult.raw.route_status = fields[i];
1377
+ } else if (fields[i] == "RI") {
1378
+ decodeResult.raw.route_status = "RI";
1379
+ decodeResult.formatted.items.push({
1380
+ type: "status",
1381
+ code: "ROUTE_STATUS",
1382
+ label: "Route Status",
1383
+ value: "Route Inactive"
1384
+ });
1306
1385
  } else {
1307
1386
  decodeResult.remaining.text += "/" + fields[i];
1308
1387
  allKnownFields = false;
1309
1388
  }
1310
1389
  }
1311
- decodeResult.raw.route_status = fields[fields.length - 1];
1312
- var text;
1313
- if (decodeResult.raw.route_status == "RP") {
1314
- text = "Route Planned";
1315
- } else if (decodeResult.raw.route_status == "RI") {
1316
- text = "Route Inactive";
1317
- } else if (decodeResult.raw.route_status == "RF") {
1318
- text = "Route Filed";
1319
- } else {
1320
- text = decodeResult.raw.route_status;
1321
- }
1322
- decodeResult.formatted.items.push({
1323
- type: "status",
1324
- code: "ROUTE_STATUS",
1325
- label: "Route Status",
1326
- value: text
1327
- });
1328
1390
  return allKnownFields;
1329
1391
  }
1392
+ function processPosition(decodeResult, value) {
1393
+ const position = CoordinateUtils.decodeStringCoordinates(value);
1394
+ if (position) {
1395
+ decodeResult.raw.position = position;
1396
+ decodeResult.formatted.items.push({
1397
+ type: "aircraft_position",
1398
+ code: "POS",
1399
+ label: "Aircraft Position",
1400
+ value: CoordinateUtils.coordinateString(position)
1401
+ });
1402
+ }
1403
+ return !!position;
1404
+ }
1330
1405
  function addArrivalAirport(decodeResult, value) {
1331
1406
  decodeResult.raw.arrival_icao = value;
1332
1407
  decodeResult.formatted.items.push({
@@ -1345,12 +1420,20 @@ function addDepartureAirport(decodeResult, value) {
1345
1420
  value: decodeResult.raw.departure_icao
1346
1421
  });
1347
1422
  }
1348
- function addDepartureRunway(decodeResult, value) {
1349
- decodeResult.raw.runway = value;
1423
+ function addRunway(decodeResult, value) {
1424
+ if (value.length === 8) {
1425
+ decodeResult.raw.arrival_runway = value.substring(4, 7);
1426
+ decodeResult.formatted.items.push({
1427
+ type: "runway",
1428
+ label: "Arrival Runway",
1429
+ value: decodeResult.raw.arrival_runway
1430
+ });
1431
+ }
1432
+ decodeResult.raw.departure_runway = value.substring(0, 3);
1350
1433
  decodeResult.formatted.items.push({
1351
1434
  type: "runway",
1352
- label: "Runway",
1353
- value: decodeResult.raw.runway
1435
+ label: "Departure Runway",
1436
+ value: decodeResult.raw.departure_runway
1354
1437
  });
1355
1438
  }
1356
1439
  function addRoute(decodeResult, value) {
@@ -1460,7 +1543,7 @@ var Label_H1_POS = class extends DecoderPlugin {
1460
1543
  qualifiers() {
1461
1544
  return {
1462
1545
  labels: ["H1"],
1463
- preambles: ["POS", "#M1BPOS"]
1546
+ preambles: ["POS", "#M1BPOS", "/.POS"]
1464
1547
  //TODO - support data before #
1465
1548
  };
1466
1549
  }
@@ -1469,30 +1552,25 @@ var Label_H1_POS = class extends DecoderPlugin {
1469
1552
  decodeResult.decoder.name = this.name;
1470
1553
  decodeResult.formatted.description = "Position Report";
1471
1554
  decodeResult.message = message;
1555
+ decodeResult.remaining.text = "";
1472
1556
  const checksum = message.text.slice(-4);
1473
- const parts = message.text.replace("#M1B", "").replace("POS", "").slice(0, -4).split(",");
1474
- console.log(parts);
1475
- if (parts.length == 1 && parts[0].startsWith("/RF")) {
1476
- decodeResult.raw.route_status == "RF";
1477
- decodeResult.formatted.items.push({
1478
- type: "status",
1479
- code: "ROUTE_STATUS",
1480
- label: "Route Status",
1481
- value: "Route Filed"
1482
- });
1483
- decodeResult.raw.route = { waypoints: parts[0].substring(3, parts[0].length).split(".").map((leg) => RouteUtils.getWaypoint(leg)) };
1484
- decodeResult.formatted.items.push({
1485
- type: "aircraft_route",
1486
- code: "ROUTE",
1487
- label: "Aircraft Route",
1488
- value: RouteUtils.routeToString(decodeResult.raw.route)
1489
- });
1490
- processChecksum(decodeResult, checksum);
1491
- decodeResult.decoded = true;
1492
- decodeResult.decoder.decodeLevel = "full";
1557
+ const header = findHeader(message.text.slice(0, -4));
1558
+ const decoded = FlightPlanUtils.processFlightPlan(decodeResult, header.split(":"));
1559
+ const parts = message.text.replace(header, "").slice(0, -4).split(",");
1560
+ if (parts.length == 1) {
1561
+ if (decoded) {
1562
+ processChecksum(decodeResult, checksum);
1563
+ decodeResult.decoded = true;
1564
+ decodeResult.decoder.decodeLevel = "full";
1565
+ } else if (decodeResult.remaining.text.length > 0) {
1566
+ processChecksum(decodeResult, checksum);
1567
+ decodeResult.decoded = true;
1568
+ decodeResult.decoder.decodeLevel = "partial";
1569
+ } else {
1570
+ decodeResult.decoded = false;
1571
+ decodeResult.decoder.decodeLevel = "none";
1572
+ }
1493
1573
  } else if (parts.length === 10) {
1494
- decodeResult.remaining.text = "";
1495
- processPosition(decodeResult, parts[0]);
1496
1574
  processAlt(decodeResult, parts[3]);
1497
1575
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1498
1576
  processTemp(decodeResult, parts[7]);
@@ -1502,8 +1580,6 @@ var Label_H1_POS = class extends DecoderPlugin {
1502
1580
  decodeResult.decoded = true;
1503
1581
  decodeResult.decoder.decodeLevel = "partial";
1504
1582
  } else if (parts.length === 11) {
1505
- decodeResult.remaining.text = "";
1506
- processPosition(decodeResult, parts[0]);
1507
1583
  processAlt(decodeResult, parts[3]);
1508
1584
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], parts[10]);
1509
1585
  processTemp(decodeResult, parts[7]);
@@ -1512,9 +1588,18 @@ var Label_H1_POS = class extends DecoderPlugin {
1512
1588
  processChecksum(decodeResult, checksum);
1513
1589
  decodeResult.decoded = true;
1514
1590
  decodeResult.decoder.decodeLevel = "partial";
1591
+ } else if (parts.length === 12) {
1592
+ const date = parts[11].substring(2, 4) + parts[11].substring(0, 2) + parts[11].substring(4, 6);
1593
+ processUnknown(decodeResult, parts[3]);
1594
+ processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6], date);
1595
+ processTemp(decodeResult, parts[7]);
1596
+ processUnknown(decodeResult, parts[8]);
1597
+ processUnknown(decodeResult, parts[9]);
1598
+ processUnknown(decodeResult, parts[10]);
1599
+ processChecksum(decodeResult, checksum);
1600
+ decodeResult.decoded = true;
1601
+ decodeResult.decoder.decodeLevel = "partial";
1515
1602
  } else if (parts.length === 14) {
1516
- decodeResult.remaining.text = "";
1517
- processPosition(decodeResult, parts[0]);
1518
1603
  processAlt(decodeResult, parts[3]);
1519
1604
  processRoute(decodeResult, parts[1], parts[2], parts[4], parts[5], parts[6]);
1520
1605
  processTemp(decodeResult, parts[7]);
@@ -1527,9 +1612,48 @@ var Label_H1_POS = class extends DecoderPlugin {
1527
1612
  processChecksum(decodeResult, checksum);
1528
1613
  decodeResult.decoded = true;
1529
1614
  decodeResult.decoder.decodeLevel = "partial";
1615
+ } else if (parts.length === 15) {
1616
+ processUnknown(decodeResult, parts[1]);
1617
+ let date = void 0;
1618
+ if (parts[2].startsWith("/DC")) {
1619
+ date = parts[2].substring(3);
1620
+ } else {
1621
+ processUnknown(decodeResult, parts[2]);
1622
+ }
1623
+ processUnknown(decodeResult, parts[3]);
1624
+ const fields = parts[4].split("/");
1625
+ for (let i = 0; i < fields.length; ++i) {
1626
+ const field = fields[i];
1627
+ if (field.startsWith("PS")) {
1628
+ processPosition2(decodeResult, field.substring(2));
1629
+ } else {
1630
+ if (i === 0) {
1631
+ processUnknown(decodeResult, field);
1632
+ } else {
1633
+ processUnknown(decodeResult, "/" + field);
1634
+ }
1635
+ }
1636
+ }
1637
+ processRoute(decodeResult, parts[7], parts[5], parts[9], parts[8], void 0, date);
1638
+ processAlt(decodeResult, parts[6]);
1639
+ processTemp(decodeResult, parts[10]);
1640
+ processUnknown(decodeResult, parts[11]);
1641
+ processUnknown(decodeResult, parts[12]);
1642
+ processUnknown(decodeResult, parts[13]);
1643
+ processUnknown(decodeResult, parts[14]);
1644
+ processChecksum(decodeResult, checksum);
1645
+ decodeResult.decoded = true;
1646
+ decodeResult.decoder.decodeLevel = "partial";
1647
+ } else if (parts.length === 21) {
1648
+ processRunway(decodeResult, parts[1]);
1649
+ processUnknown(decodeResult, parts.slice(2, 11).join(","));
1650
+ processTemp(decodeResult, parts[11]);
1651
+ processUnknown(decodeResult, parts.slice(12, 20).join(","));
1652
+ FlightPlanUtils.processFlightPlan(decodeResult, parts[20].split(":"));
1653
+ processChecksum(decodeResult, checksum);
1654
+ decodeResult.decoded = true;
1655
+ decodeResult.decoder.decodeLevel = "partial";
1530
1656
  } else if (parts.length === 32) {
1531
- decodeResult.remaining.text = "";
1532
- processPosition(decodeResult, parts[0]);
1533
1657
  processRunway(decodeResult, parts[1]);
1534
1658
  const time = parts[2];
1535
1659
  processUnknown(decodeResult, parts[3]);
@@ -1547,14 +1671,14 @@ var Label_H1_POS = class extends DecoderPlugin {
1547
1671
  processAlt(decodeResult, parts[22]);
1548
1672
  processUnknown(decodeResult, parts.slice(23, 31).join(","));
1549
1673
  const allProcessed = FlightPlanUtils.processFlightPlan(decodeResult, (parts[31] + checksum).split(":"));
1550
- processRoute(decodeResult, past, time, next, eta, "?");
1674
+ processRoute(decodeResult, past, time, next, eta);
1551
1675
  decodeResult.decoded = true;
1552
1676
  decodeResult.decoder.decodeLevel = "partial";
1553
1677
  } else {
1554
1678
  if (options.debug) {
1555
1679
  console.log(`Decoder: Unknown H1 message: ${message.text}`);
1556
1680
  }
1557
- decodeResult.remaining.text = message.text;
1681
+ decodeResult.remaining.text += message.text;
1558
1682
  decodeResult.decoded = false;
1559
1683
  decodeResult.decoder.decodeLevel = "none";
1560
1684
  }
@@ -1564,18 +1688,17 @@ var Label_H1_POS = class extends DecoderPlugin {
1564
1688
  function processUnknown(decodeResult, value) {
1565
1689
  decodeResult.remaining.text += "," + value;
1566
1690
  }
1567
- function processPosition(decodeResult, value) {
1691
+ function processPosition2(decodeResult, value) {
1568
1692
  const position = CoordinateUtils.decodeStringCoordinates(value);
1569
- decodeResult.raw.latitude_direction = position.latitudeDirection;
1570
- decodeResult.raw.latitude = Math.abs(position.latitude);
1571
- decodeResult.raw.longitude_direction = position.longitudeDirection;
1572
- decodeResult.raw.longitude = Math.abs(position.longitude);
1573
- decodeResult.formatted.items.push({
1574
- type: "aircraft_position",
1575
- code: "POS",
1576
- label: "Aircraft Position",
1577
- value: CoordinateUtils.coordinateString(position)
1578
- });
1693
+ if (position) {
1694
+ decodeResult.raw.position = position;
1695
+ decodeResult.formatted.items.push({
1696
+ type: "aircraft_position",
1697
+ code: "POS",
1698
+ label: "Aircraft Position",
1699
+ value: CoordinateUtils.coordinateString(position)
1700
+ });
1701
+ }
1579
1702
  }
1580
1703
  function processAlt(decodeResult, value) {
1581
1704
  decodeResult.raw.altitude = Number(value) * 100;
@@ -1596,11 +1719,11 @@ function processTemp(decodeResult, value) {
1596
1719
  });
1597
1720
  }
1598
1721
  function processRunway(decodeResult, value) {
1599
- decodeResult.raw.runway = value.replace("RW", "");
1722
+ decodeResult.raw.arrival_runway = value.replace("RW", "");
1600
1723
  decodeResult.formatted.items.push({
1601
1724
  type: "runway",
1602
- label: "Runway",
1603
- value: decodeResult.raw.runway
1725
+ label: "Arrival Runway",
1726
+ value: decodeResult.raw.arrival_runway
1604
1727
  });
1605
1728
  }
1606
1729
  function processGndspd(decodeResult, value) {
@@ -1613,16 +1736,17 @@ function processGndspd(decodeResult, value) {
1613
1736
  });
1614
1737
  }
1615
1738
  function processRoute(decodeResult, last, time, next, eta, then, date) {
1616
- let waypoints;
1617
- waypoints = date === void 0 ? [
1618
- { name: last || "?,", time: DateTimeUtils.convertHHMMSSToTod(time), timeFormat: "tod" },
1619
- { name: next || "?", time: DateTimeUtils.convertHHMMSSToTod(eta), timeFormat: "tod" },
1620
- { name: then || "?" }
1621
- ] : [
1622
- { name: last || "?,", time: DateTimeUtils.convertDateTimeToEpoch(time, date), timeFormat: "epoch" },
1623
- { name: next || "?", time: DateTimeUtils.convertDateTimeToEpoch(eta, date), timeFormat: "epoch" },
1624
- { name: then || "?" }
1625
- ];
1739
+ const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
1740
+ const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
1741
+ const timeFormat = date ? "epoch" : "tod";
1742
+ const lastWaypoint = RouteUtils.getWaypoint(last);
1743
+ lastWaypoint.time = lastTime;
1744
+ lastWaypoint.timeFormat = timeFormat;
1745
+ const nextWaypoint = RouteUtils.getWaypoint(next);
1746
+ nextWaypoint.time = nextTime;
1747
+ nextWaypoint.timeFormat = timeFormat;
1748
+ const thenWaypoint = RouteUtils.getWaypoint(then || "?");
1749
+ const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
1626
1750
  decodeResult.raw.route = { waypoints };
1627
1751
  decodeResult.formatted.items.push({
1628
1752
  type: "aircraft_route",
@@ -1640,6 +1764,70 @@ function processChecksum(decodeResult, value) {
1640
1764
  value: "0x" + ("0000" + decodeResult.raw.checksum.toString(16)).slice(-4)
1641
1765
  });
1642
1766
  }
1767
+ function findHeader(text) {
1768
+ const parts = text.split(",");
1769
+ const header = parts[0];
1770
+ if (header.indexOf("/TS") === -1) {
1771
+ return header;
1772
+ }
1773
+ return parts[0] + "," + parts[1];
1774
+ }
1775
+
1776
+ // lib/plugins/Label_H1_WRN.ts
1777
+ var Label_H1_WRN = class extends DecoderPlugin {
1778
+ name = "label-h1-wrn";
1779
+ qualifiers() {
1780
+ return {
1781
+ labels: ["H1"],
1782
+ preambles: ["WRN", "#CFBWRN"]
1783
+ };
1784
+ }
1785
+ decode(message, options = {}) {
1786
+ let decodeResult = this.defaultResult;
1787
+ decodeResult.decoder.name = this.name;
1788
+ decodeResult.formatted.description = "Warning Message";
1789
+ decodeResult.message = message;
1790
+ const parts = message.text.split("/WN");
1791
+ if (parts.length > 1) {
1792
+ decodeResult.remaining.text = "";
1793
+ const fields = parts[0].split("/");
1794
+ for (let i = 1; i < fields.length; i++) {
1795
+ const field = fields[i];
1796
+ if (field.startsWith("PN")) {
1797
+ processUnknown2(decodeResult, "/" + field);
1798
+ } else {
1799
+ processUnknown2(decodeResult, "/" + field);
1800
+ }
1801
+ }
1802
+ const data = parts[1].substring(0, 20);
1803
+ const msg = parts[1].substring(20);
1804
+ const datetime = data.substring(0, 12);
1805
+ const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
1806
+ processUnknown2(decodeResult, data.substring(12));
1807
+ decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
1808
+ decodeResult.raw.warning_message = msg;
1809
+ decodeResult.formatted.items.push({
1810
+ type: "warning",
1811
+ code: "WRN",
1812
+ label: "Warning Message",
1813
+ value: decodeResult.raw.warning_message
1814
+ });
1815
+ decodeResult.decoded = true;
1816
+ decodeResult.decoder.decodeLevel = "partial";
1817
+ } else {
1818
+ if (options.debug) {
1819
+ console.log(`Decoder: Unknown H1 message: ${message.text}`);
1820
+ }
1821
+ decodeResult.remaining.text = message.text;
1822
+ decodeResult.decoded = false;
1823
+ decodeResult.decoder.decodeLevel = "none";
1824
+ }
1825
+ return decodeResult;
1826
+ }
1827
+ };
1828
+ function processUnknown2(decodeResult, value) {
1829
+ decodeResult.remaining.text += value;
1830
+ }
1643
1831
 
1644
1832
  // lib/plugins/Label_SQ.ts
1645
1833
  var Label_SQ = class extends DecoderPlugin {
@@ -1922,7 +2110,7 @@ var Label_QQ = class extends DecoderPlugin {
1922
2110
 
1923
2111
  // lib/utils/miam.ts
1924
2112
  import * as Base85 from "base85";
1925
- import * as Zlib from "zlib";
2113
+ import * as zlib from "minizlib";
1926
2114
  var MIAMCoreV1CRCLength = 4;
1927
2115
  var MIAMCoreV2CRCLength = 2;
1928
2116
  var MIAMCoreUtils = class {
@@ -2632,7 +2820,10 @@ var MIAMCoreUtils = class {
2632
2820
  if (body !== void 0 && body.length > 0) {
2633
2821
  if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
2634
2822
  try {
2635
- pduData = Zlib.inflateRawSync(body, { windowBits: 15 });
2823
+ const decompress = new zlib.InflateRaw({ windowBits: 15 });
2824
+ decompress.write(body);
2825
+ decompress.flush(zlib.constants.Z_SYNC_FLUSH);
2826
+ pduData = decompress.read();
2636
2827
  } catch (e) {
2637
2828
  pduErrors.push("Inflation failed for body: " + e);
2638
2829
  }
@@ -2744,6 +2935,7 @@ var MessageDecoder = class {
2744
2935
  this.registerPlugin(new Label_B6_Forwardslash(this));
2745
2936
  this.registerPlugin(new Label_H1_FPN(this));
2746
2937
  this.registerPlugin(new Label_H1_POS(this));
2938
+ this.registerPlugin(new Label_H1_WRN(this));
2747
2939
  this.registerPlugin(new Label_80(this));
2748
2940
  this.registerPlugin(new Label_8E(this));
2749
2941
  this.registerPlugin(new Label_1M_Slash(this));