metar-taf-parser 7.1.3 → 8.0.0

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/README.md CHANGED
@@ -32,6 +32,8 @@ The `parseMetar` & `parseTAF` functions are designed to parse the raw report str
32
32
 
33
33
  #### `parseMetar`
34
34
 
35
+ If the payload begins with [`METAR` or `SPECI`](http://www.bom.gov.au/aviation/data/education/metar-speci.pdf), that will be added as the `type`.
36
+
35
37
  ```ts
36
38
  import { parseMetar } from "metar-taf-parser";
37
39
 
@@ -1,3 +1,7 @@
1
+ declare enum MetarType {
2
+ METAR = "METAR",
3
+ SPECI = "SPECI"
4
+ }
1
5
  declare enum CloudQuantity {
2
6
  /**
3
7
  * Sky clear
@@ -326,6 +330,41 @@ declare enum TurbulenceIntensity {
326
330
  /** Extreme turbulence */
327
331
  Extreme = "X"
328
332
  }
333
+ declare enum DepositType {
334
+ /** (runway clearance in progress) */
335
+ NotReported = "/",
336
+ ClearDry = "0",
337
+ Damp = "1",
338
+ WetWaterPatches = "2",
339
+ RimeFrostCovered = "3",
340
+ DrySnow = "4",
341
+ WetSnow = "5",
342
+ Slush = "6",
343
+ Ice = "7",
344
+ CompactedSnow = "8",
345
+ FrozenRidges = "9"
346
+ }
347
+ declare enum DepositCoverage {
348
+ NotReported = "/",
349
+ Less10 = "1",
350
+ From11To25 = "2",
351
+ From26To50 = "5",
352
+ From51To100 = "9"
353
+ }
354
+ declare enum AltimeterUnit {
355
+ /**
356
+ * Inches of mercury (inHg)
357
+ *
358
+ * e.g. A2994 parses as 29.94 inHg
359
+ */
360
+ InHg = "inHg",
361
+ /**
362
+ * Hectopascals (hPa), also known as millibars
363
+ *
364
+ * e.g. Q1018 parses as 1018 millibars
365
+ */
366
+ HPa = "hPa"
367
+ }
329
368
 
330
369
  declare const _default: {
331
370
  CloudQuantity: {
@@ -1131,6 +1170,10 @@ interface IWeatherCondition {
1131
1170
  phenomenons: Phenomenon[];
1132
1171
  }
1133
1172
  declare function isWeatherConditionValid(weather: IWeatherCondition): boolean;
1173
+ interface IAltimeter {
1174
+ value: number;
1175
+ unit: AltimeterUnit;
1176
+ }
1134
1177
  interface ITemperature {
1135
1178
  temperature: number;
1136
1179
  day: number;
@@ -1139,7 +1182,11 @@ interface ITemperature {
1139
1182
  interface ITemperatureDated extends ITemperature {
1140
1183
  date: Date;
1141
1184
  }
1142
- interface IRunwayInfo {
1185
+ declare type RunwayInfo = IRunwayInfoRange | IRunwayInfoDeposit;
1186
+ interface IBaseRunwayInfo {
1187
+ name: string;
1188
+ }
1189
+ interface IRunwayInfoRange extends IBaseRunwayInfo {
1143
1190
  name: string;
1144
1191
  minRange: number;
1145
1192
  maxRange?: number;
@@ -1153,6 +1200,50 @@ interface IRunwayInfo {
1153
1200
  trend?: RunwayInfoTrend;
1154
1201
  unit: RunwayInfoUnit;
1155
1202
  }
1203
+ interface IRunwayInfoDeposit extends IBaseRunwayInfo {
1204
+ depositType?: DepositType;
1205
+ coverage?: DepositCoverage;
1206
+ /**
1207
+ * Depth of deposit
1208
+ *
1209
+ * Note: the quoted depth is the mean of a number of reading or if operationally significant the greatest depth measured.
1210
+ *
1211
+ * | Value | Description |
1212
+ * | ----- | ----------- |
1213
+ * | `"00"` | Less than 1mm |
1214
+ * | `"01"` to `"90"` | Measurement in mm |
1215
+ * | `"92"` | 10cm |
1216
+ * | `"93"` | 15cm |
1217
+ * | `"94"` | 20cm |
1218
+ * | `"95"` | 25cm |
1219
+ * | `"96"` | 30cm |
1220
+ * | `"97"` | 35cm |
1221
+ * | `"98"` | 40cm or more |
1222
+ * | `"99"` | Runway not operational due to snow, slush, ice, large drifts or runway clearance, depth not reported |
1223
+ * | `"//"` | Not operationally significant or not measurable |
1224
+ */
1225
+ thickness?: string;
1226
+ /**
1227
+ * Friction Coefficient or Braking Action
1228
+ *
1229
+ * Note: Where braking action is assessed at a number of points along the runway the mean value will be transmitted or if operationally significant the lowest value.
1230
+ *
1231
+ * If measuring equipment does not allow measurement of friction with satisfactory reliability (such as contaminated by wet snow, slush or loose snow) the figure 99 will be used.
1232
+ *
1233
+ * | Value | Description |
1234
+ * | ----- | ----------- |
1235
+ * | `"28"` | Friction coefficient 0.28
1236
+ * | `"35"` | Friction coefficient 0.35
1237
+ * | `"91"` | Braking action poor
1238
+ * | `"92"` | Braking action medium to poor
1239
+ * | `"93"` | Braking action medium
1240
+ * | `"94"` | Braking action medium to good
1241
+ * | `"95"` | Braking action good
1242
+ * | `"99"` | Figures unreliable
1243
+ * | `"//"` | Braking action not reported or runway not operations or airport closed.
1244
+ */
1245
+ brakingCapacity?: string;
1246
+ }
1156
1247
  interface ICloud {
1157
1248
  height?: number;
1158
1249
  quantity: CloudQuantity;
@@ -1222,11 +1313,12 @@ interface IAbstractWeatherCodeDated extends IAbstractWeatherCode {
1222
1313
  issued: Date;
1223
1314
  }
1224
1315
  interface IMetar extends IAbstractWeatherCode {
1316
+ type?: MetarType;
1225
1317
  temperature?: number;
1226
1318
  dewPoint?: number;
1227
- altimeter?: number;
1319
+ altimeter?: IAltimeter;
1228
1320
  nosig?: true;
1229
- runwaysInfo: IRunwayInfo[];
1321
+ runwaysInfo: RunwayInfo[];
1230
1322
  /**
1231
1323
  * Not used in North America
1232
1324
  */
@@ -1462,4 +1554,4 @@ declare function parseTAF(rawTAF: string, options?: IMetarTAFParserOptions): ITA
1462
1554
  declare function parseTAF(rawTAF: string, options?: IMetarTAFParserOptionsDated): ITAFDated;
1463
1555
  declare function parseTAFAsForecast(rawTAF: string, options: IMetarTAFParserOptionsDated): IForecastContainer;
1464
1556
 
1465
- export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, Distance, DistanceUnit, Forecast, IAbstractTrend, IAbstractValidity, IAbstractWeatherCode, IAbstractWeatherCodeDated, IAbstractWeatherContainer, IBaseRemark, IBaseTAFTrend, ICeilingHeightRemark, ICeilingSecondLocationRemark, ICloud, ICompositeForecast, IEndValidity, IFMValidity, IFlags, IForecastContainer, IHourlyMaximumMinimumTemperatureRemark, IHourlyMaximumTemperatureRemark, IHourlyMinimumTemperatureRemark, IHourlyPrecipitationAmountRemark, IHourlyPressureRemark, IHourlyTemperatureDewPointRemark, IIceAccretionRemark, IIcing, IMetar, IMetarDated, IMetarTAFParserOptions, IMetarTAFParserOptionsDated, IMetarTrend, IMetarTrendTime, IObscurationRemark, IPrecipitationAmount24HourRemark, IPrecipitationAmount36HourRemark, IPrecipitationBegEndRemark, IPrevailingVisibilityRemark, IRunwayInfo, ISeaLevelPressureRemark, ISecondLocationVisibilityRemark, ISectorVisibilityRemark, ISmallHailSizeRemark, ISnowIncreaseRemark, ISnowPelletsRemark, ISunshineDurationRemark, ISurfaceVisibilityRemark, ITAF, ITAFDated, ITafGroups, ITemperature, ITemperatureDated, IThunderStormLocationMovingRemark, IThunderStormLocationRemark, ITime, ITornadicActivityBegEndRemark, ITornadicActivityBegRemark, ITornadicActivityEndRemark, ITowerVisibilityRemark, ITurbulence, IUnknownRemark, IValidity, IValidityDated, IVariableSkyHeightRemark, IVariableSkyRemark, IVirgaDirectionRemark, IWaterEquivalentSnowRemark, IWeatherCondition, IWind, IWindPeakCommandRemark, IWindShear, IWindShiftFropaRemark, IcingIntensity, Intensity, InvalidWeatherStatementError, Locale, ParseError, Phenomenon, Remark, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TAFTrend, TAFTrendDated, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, Visibility, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
1557
+ export { AltimeterUnit, CloudQuantity, CloudType, CommandExecutionError, DepositCoverage, DepositType, Descriptive, Direction, Distance, DistanceUnit, Forecast, IAbstractTrend, IAbstractValidity, IAbstractWeatherCode, IAbstractWeatherCodeDated, IAbstractWeatherContainer, IAltimeter, IBaseRemark, IBaseRunwayInfo, IBaseTAFTrend, ICeilingHeightRemark, ICeilingSecondLocationRemark, ICloud, ICompositeForecast, IEndValidity, IFMValidity, IFlags, IForecastContainer, IHourlyMaximumMinimumTemperatureRemark, IHourlyMaximumTemperatureRemark, IHourlyMinimumTemperatureRemark, IHourlyPrecipitationAmountRemark, IHourlyPressureRemark, IHourlyTemperatureDewPointRemark, IIceAccretionRemark, IIcing, IMetar, IMetarDated, IMetarTAFParserOptions, IMetarTAFParserOptionsDated, IMetarTrend, IMetarTrendTime, IObscurationRemark, IPrecipitationAmount24HourRemark, IPrecipitationAmount36HourRemark, IPrecipitationBegEndRemark, IPrevailingVisibilityRemark, IRunwayInfoDeposit, IRunwayInfoRange, ISeaLevelPressureRemark, ISecondLocationVisibilityRemark, ISectorVisibilityRemark, ISmallHailSizeRemark, ISnowIncreaseRemark, ISnowPelletsRemark, ISunshineDurationRemark, ISurfaceVisibilityRemark, ITAF, ITAFDated, ITafGroups, ITemperature, ITemperatureDated, IThunderStormLocationMovingRemark, IThunderStormLocationRemark, ITime, ITornadicActivityBegEndRemark, ITornadicActivityBegRemark, ITornadicActivityEndRemark, ITowerVisibilityRemark, ITurbulence, IUnknownRemark, IValidity, IValidityDated, IVariableSkyHeightRemark, IVariableSkyRemark, IVirgaDirectionRemark, IWaterEquivalentSnowRemark, IWeatherCondition, IWind, IWindPeakCommandRemark, IWindShear, IWindShiftFropaRemark, IcingIntensity, Intensity, InvalidWeatherStatementError, Locale, MetarType, ParseError, Phenomenon, Remark, RemarkType, RunwayInfo, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TAFTrend, TAFTrendDated, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, Visibility, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
@@ -183,6 +183,11 @@ class CeilingSecondLocationCommand extends Command {
183
183
  }
184
184
  _CeilingSecondLocationCommand_regex = new WeakMap();
185
185
 
186
+ var MetarType;
187
+ (function (MetarType) {
188
+ MetarType["METAR"] = "METAR";
189
+ MetarType["SPECI"] = "SPECI";
190
+ })(MetarType || (MetarType = {}));
186
191
  var CloudQuantity;
187
192
  (function (CloudQuantity) {
188
193
  /**
@@ -526,6 +531,44 @@ var TurbulenceIntensity;
526
531
  /** Extreme turbulence */
527
532
  TurbulenceIntensity["Extreme"] = "X";
528
533
  })(TurbulenceIntensity || (TurbulenceIntensity = {}));
534
+ var DepositType;
535
+ (function (DepositType) {
536
+ /** (runway clearance in progress) */
537
+ DepositType["NotReported"] = "/";
538
+ DepositType["ClearDry"] = "0";
539
+ DepositType["Damp"] = "1";
540
+ DepositType["WetWaterPatches"] = "2";
541
+ DepositType["RimeFrostCovered"] = "3";
542
+ DepositType["DrySnow"] = "4";
543
+ DepositType["WetSnow"] = "5";
544
+ DepositType["Slush"] = "6";
545
+ DepositType["Ice"] = "7";
546
+ DepositType["CompactedSnow"] = "8";
547
+ DepositType["FrozenRidges"] = "9";
548
+ })(DepositType || (DepositType = {}));
549
+ var DepositCoverage;
550
+ (function (DepositCoverage) {
551
+ DepositCoverage["NotReported"] = "/";
552
+ DepositCoverage["Less10"] = "1";
553
+ DepositCoverage["From11To25"] = "2";
554
+ DepositCoverage["From26To50"] = "5";
555
+ DepositCoverage["From51To100"] = "9";
556
+ })(DepositCoverage || (DepositCoverage = {}));
557
+ var AltimeterUnit;
558
+ (function (AltimeterUnit) {
559
+ /**
560
+ * Inches of mercury (inHg)
561
+ *
562
+ * e.g. A2994 parses as 29.94 inHg
563
+ */
564
+ AltimeterUnit["InHg"] = "inHg";
565
+ /**
566
+ * Hectopascals (hPa), also known as millibars
567
+ *
568
+ * e.g. Q1018 parses as 1018 millibars
569
+ */
570
+ AltimeterUnit["HPa"] = "hPa";
571
+ })(AltimeterUnit || (AltimeterUnit = {}));
529
572
 
530
573
  function degreesToCardinal(input) {
531
574
  const degrees = +input;
@@ -607,9 +650,6 @@ function convertTemperature(input) {
607
650
  return -pySplit(input, "M")[1];
608
651
  return +input;
609
652
  }
610
- function convertInchesMercuryToPascal(input) {
611
- return 33.8639 * input;
612
- }
613
653
  /**
614
654
  * Converts number `.toFixed(1)` before outputting to match python implementation
615
655
  */
@@ -2010,7 +2050,10 @@ class AltimeterCommand {
2010
2050
  const matches = input.match(__classPrivateFieldGet(this, _AltimeterCommand_regex, "f"));
2011
2051
  if (!matches)
2012
2052
  throw new UnexpectedParseError("Match not found");
2013
- metar.altimeter = Math.trunc(+matches[1]);
2053
+ metar.altimeter = {
2054
+ value: +matches[1],
2055
+ unit: AltimeterUnit.HPa,
2056
+ };
2014
2057
  }
2015
2058
  }
2016
2059
  _AltimeterCommand_regex = new WeakMap();
@@ -2028,24 +2071,41 @@ class AltimeterMercuryCommand {
2028
2071
  if (!matches)
2029
2072
  throw new UnexpectedParseError("Match not found");
2030
2073
  const mercury = +matches[1] / 100;
2031
- metar.altimeter = Math.trunc(convertInchesMercuryToPascal(mercury));
2074
+ metar.altimeter = {
2075
+ value: mercury,
2076
+ unit: AltimeterUnit.InHg,
2077
+ };
2032
2078
  }
2033
2079
  }
2034
2080
  _AltimeterMercuryCommand_regex = new WeakMap();
2035
2081
 
2036
- var _RunwayCommand_genericRegex, _RunwayCommand_runwayMaxRangeRegex, _RunwayCommand_runwayRegex;
2082
+ var _RunwayCommand_genericRegex, _RunwayCommand_runwayMaxRangeRegex, _RunwayCommand_runwayRegex, _RunwayCommand_runwayDepositRegex;
2037
2083
  class RunwayCommand {
2038
2084
  constructor() {
2039
2085
  _RunwayCommand_genericRegex.set(this, /^(R\d{2}\w?\/)/);
2040
2086
  _RunwayCommand_runwayMaxRangeRegex.set(this, /^R(\d{2}\w?)\/(\d{4})V(\d{3,4})([UDN])?(FT)?/);
2041
2087
  _RunwayCommand_runwayRegex.set(this, /^R(\d{2}\w?)\/([MP])?(\d{4})([UDN])?(FT)?$/);
2088
+ _RunwayCommand_runwayDepositRegex.set(this, /^R(\d{2}\w?)\/([/\d])([/\d])(\/\/|\d{2})(\/\/|\d{2})$/);
2042
2089
  }
2043
2090
  canParse(input) {
2044
2091
  return __classPrivateFieldGet(this, _RunwayCommand_genericRegex, "f").test(input);
2045
2092
  }
2046
2093
  execute(metar, input) {
2047
- // TODO idk if this matches super well...
2048
- if (__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f").test(input)) {
2094
+ if (__classPrivateFieldGet(this, _RunwayCommand_runwayDepositRegex, "f").test(input)) {
2095
+ const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayDepositRegex, "f"));
2096
+ if (!matches)
2097
+ throw new UnexpectedParseError("Should be able to parse");
2098
+ const depositType = as(matches[2], DepositType);
2099
+ const coverage = as(matches[3], DepositCoverage);
2100
+ metar.runwaysInfo.push({
2101
+ name: matches[1],
2102
+ depositType,
2103
+ coverage,
2104
+ thickness: matches[4],
2105
+ brakingCapacity: matches[5],
2106
+ });
2107
+ }
2108
+ else if (__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f").test(input)) {
2049
2109
  const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f"));
2050
2110
  if (!matches)
2051
2111
  throw new UnexpectedParseError("Should be able to parse");
@@ -2080,7 +2140,7 @@ class RunwayCommand {
2080
2140
  }
2081
2141
  }
2082
2142
  }
2083
- _RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap();
2143
+ _RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap(), _RunwayCommand_runwayDepositRegex = new WeakMap();
2084
2144
 
2085
2145
  var _TemperatureCommand_regex;
2086
2146
  class TemperatureCommand {
@@ -2438,6 +2498,9 @@ class MetarParser extends AbstractParser {
2438
2498
  parse(input) {
2439
2499
  const metarTab = this.tokenize(input);
2440
2500
  let index = 0;
2501
+ const type = this.parseType(metarTab[index]);
2502
+ if (type)
2503
+ index++;
2441
2504
  // Only parse flag if precedes station identifier
2442
2505
  if (isStation(metarTab[index + 1])) {
2443
2506
  var flags = findFlags(metarTab[index]);
@@ -2445,8 +2508,9 @@ class MetarParser extends AbstractParser {
2445
2508
  index += 1;
2446
2509
  }
2447
2510
  const metar = {
2448
- ...parseDeliveryTime(metarTab[index + 1]),
2511
+ type,
2449
2512
  station: metarTab[index],
2513
+ ...parseDeliveryTime(metarTab[index + 1]),
2450
2514
  ...flags,
2451
2515
  message: input,
2452
2516
  remarks: [],
@@ -2492,6 +2556,12 @@ class MetarParser extends AbstractParser {
2492
2556
  }
2493
2557
  return metar;
2494
2558
  }
2559
+ parseType(token) {
2560
+ for (const type in MetarType) {
2561
+ if (token === MetarType[type])
2562
+ return type;
2563
+ }
2564
+ }
2495
2565
  }
2496
2566
  _MetarParser_commandSupplier = new WeakMap();
2497
2567
  /**
@@ -3023,4 +3093,4 @@ function parse(rawReport, options, parser, datesHydrator) {
3023
3093
  }
3024
3094
  }
3025
3095
 
3026
- export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, DistanceUnit, IcingIntensity, Intensity, InvalidWeatherStatementError, ParseError, Phenomenon, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
3096
+ export { AltimeterUnit, CloudQuantity, CloudType, CommandExecutionError, DepositCoverage, DepositType, Descriptive, Direction, DistanceUnit, IcingIntensity, Intensity, InvalidWeatherStatementError, MetarType, ParseError, Phenomenon, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metar-taf-parser",
3
- "version": "7.1.3",
3
+ "version": "8.0.0",
4
4
  "description": "Parse METAR and TAF reports",
5
5
  "homepage": "https://aeharding.github.io/metar-taf-parser",
6
6
  "keywords": [