avwx.forecast.nbm

NBH

The NBH report is a 25-hour forecast based on the National Blend of Models and is only valid for ICAO stations in the United States and Puerto Rico, and US Virgin Islands. Reports are in 1-hour increments and are published near the top of every hour.

NBS

The NBS report is a short-range forecast (6-72 hours) based on the National Blend of Models and is only valid for ICAO stations in the United States and Puerto Rico, and US Virgin Islands. Reports are in 3-hour increments and published near the top of every hour.

NBE

The NBE report is an extended-range forecast (24-192 hours) based on the National Blend of Models and is only valid for ICAO stations in the United States and Puerto Rico, and US Virgin Islands. Reports are in 12-hour increments and published near the top of every hour.

NBX

The NBX report is a continuation of the NBE forecast (204-264 hours) based on the National Blend of Models and is only valid for ICAO stations in the United States and Puerto Rico, and US Virgin Islands. Reports are in 12-hour increments and published near the top of every hour.

  1"""
  2# NBH
  3
  4The NBH report is a 25-hour forecast based on the
  5[National Blend of Models](https://vlab.noaa.gov/web/mdl/nbm) and is only valid
  6for ICAO stations in the United States and Puerto Rico, and US Virgin Islands.
  7Reports are in 1-hour increments and are published near the top of every hour.
  8
  9# NBS
 10
 11The NBS report is a
 12short-range forecast (6-72 hours) based on the
 13[National Blend of Models](https://vlab.noaa.gov/web/mdl/nbm) and is only valid
 14for ICAO stations in the United States and Puerto Rico, and US Virgin Islands.
 15Reports are in 3-hour increments and published near the top of every hour.
 16
 17# NBE
 18
 19The NBE report is an extended-range forecast (24-192 hours) based on the
 20[National Blend of Models](https://vlab.noaa.gov/web/mdl/nbm) and is only valid
 21for ICAO stations in the United States and Puerto Rico, and US Virgin Islands.
 22Reports are in 12-hour increments and published near the top of every hour.
 23
 24# NBX
 25
 26The NBX report is a continuation of the NBE forecast (204-264 hours) based on the
 27[National Blend of Models](https://vlab.noaa.gov/web/mdl/nbm) and is only valid
 28for ICAO stations in the United States and Puerto Rico, and US Virgin Islands.
 29Reports are in 12-hour increments and published near the top of every hour.
 30"""
 31
 32# Reference: https://www.weather.gov/mdl/nbm_textcard_v32
 33
 34# pylint: disable=too-many-arguments
 35
 36# stdlib
 37from contextlib import suppress
 38from typing import Callable, Dict, List, Optional, Tuple, Union
 39
 40try:
 41    from typing import TypeAlias
 42except ImportError:
 43    from typing_extensions import TypeAlias
 44
 45# module
 46from avwx import structs
 47from avwx.service.files import NOAA_NBM
 48from avwx.static.gfs import UNITS
 49from .base import (
 50    Forecast,
 51    _decimal_10,
 52    _decimal_100,
 53    _direction,
 54    _find_time_periods,
 55    _init_parse,
 56    _numbers,
 57    _number_100,
 58    _parse_lines,
 59    _split_line,
 60    _trim_lines,
 61)
 62
 63DataT: TypeAlias = Union[structs.NbhData, structs.NbsData, structs.NbeData]
 64PeriodT: TypeAlias = Union[structs.NbhPeriod, structs.NbsPeriod, structs.NbePeriod]
 65
 66_UNITS = {
 67    **UNITS,
 68    "accumulation": "in",
 69    "duration": "hour",
 70    "solar_radiation": "W/m2",
 71    "wave_height": "ft",
 72}
 73
 74
 75_CEILING = {
 76    # 888 is code but processed as 88800 due to postfix
 77    "88800": (None, "unlimited")
 78}
 79_WIND = {"NG": (0, "zero")}
 80
 81
 82def _ceiling(line: str, size: int = 3) -> List[Optional[structs.Number]]:
 83    """Parse line into Number objects handling ceiling special units"""
 84    return _numbers(line, size, postfix="00", special=_CEILING)
 85
 86
 87def _wind(line: str, size: int = 3) -> List[Optional[structs.Number]]:
 88    """Parse line into Number objects handling wind special units"""
 89    return _numbers(line, size, special=_WIND)
 90
 91
 92_HANDLERS: Dict[str, Tuple[str, Callable]] = {
 93    "X/N": ("temperature_minmax", _numbers),
 94    "TMP": ("temperature", _numbers),
 95    "DPT": ("dewpoint", _numbers),
 96    "SKY": ("sky_cover", _numbers),
 97    "WDR": ("wind_direction", _direction),
 98    "WSP": ("wind_speed", _wind),
 99    "GST": ("wind_gust", _wind),
100    "DUR": ("precip_duration", _numbers),
101    "PZR": ("freezing_precip", _numbers),
102    "PSN": ("snow", _numbers),
103    "PPL": ("sleet", _numbers),
104    "PRA": ("rain", _numbers),
105    "SLV": ("snow_level", _number_100),
106    "SOL": ("solar_radiation", _numbers),
107    "SWH": ("wave_height", _numbers),
108}
109
110_HOUR_HANDLERS: Dict[str, Tuple[str, Callable]] = {
111    "P": ("precip_chance", _numbers),
112    "Q": ("precip_amount", _decimal_100),
113    "T": ("thunderstorm", _numbers),
114    "S": ("snow_amount", _decimal_10),
115    "I": ("icing_amount", _decimal_100),
116}
117
118_NBHS_HANDLERS: Dict[str, Tuple[str, Callable]] = {
119    "CIG": ("ceiling", _ceiling),
120    "VIS": ("visibility", _decimal_10),
121    "LCB": ("cloud_base", _number_100),
122    "MHT": ("mixing_height", _number_100),
123    "TWD": ("transport_wind_direction", _direction),
124    "TWS": ("transport_wind_speed", _numbers),
125    "HID": ("haines", _numbers),
126}
127
128
129def _parse_factory(
130    data_class: DataT,
131    period_class: PeriodT,
132    handlers: Dict[str, Tuple[str, Callable]],
133    hours: int = 2,
134    size: int = 3,
135    prefix: int = 4,
136) -> Callable:
137    """Creates handler function for static and computed keys"""
138
139    handlers = {**_HANDLERS, **handlers}
140
141    def handle(key: str) -> Tuple:
142        """Returns response key(s) and value handler for a line key"""
143        with suppress(KeyError):
144            return handlers[key]
145        if not key[1:].isdigit():
146            raise KeyError
147        root, handler = _HOUR_HANDLERS[key[0]]
148        return f"{root}_{key[1:].lstrip('0')}", handler
149
150    def parse(report: str) -> Optional[structs.ReportData]:
151        """Parser for NBM reports"""
152        if not report:
153            return None
154        data, lines = _init_parse(report)
155        lines = _trim_lines(lines, 2)
156        period_strings = _split_line(lines[hours], size, prefix)
157        timestamp = data.time.dt if data.time else None
158        periods = _find_time_periods(period_strings, timestamp)
159        data_lines = lines[hours + 1 :]
160        # Normalize line prefix length
161        if prefix != 4:
162            indexes = (4, prefix)
163            start, end = min(indexes), max(indexes)
164            data_lines = [l[:start] + l[end:] for l in data_lines]
165        _parse_lines(periods, data_lines, handle, size)
166        return data_class(  # type: ignore
167            raw=data.raw,
168            sanitized=data.sanitized,
169            station=data.station,
170            time=data.time,
171            remarks=data.remarks,
172            forecast=[period_class(**p) for p in periods],  # type: ignore
173        )
174
175    return parse
176
177
178parse_nbh: Callable[[str], structs.NbhData] = _parse_factory(
179    structs.NbhData, structs.NbhPeriod, _NBHS_HANDLERS, hours=1  # type: ignore
180)
181parse_nbs: Callable[[str], structs.NbsData] = _parse_factory(
182    structs.NbsData, structs.NbsPeriod, _NBHS_HANDLERS  # type: ignore
183)
184parse_nbe: Callable[[str], structs.NbeData] = _parse_factory(
185    structs.NbeData, structs.NbePeriod, {}, size=4, prefix=5  # type: ignore
186)
187parse_nbx: Callable[[str], structs.NbeData] = _parse_factory(
188    structs.NbxData, structs.NbxPeriod, {}, size=4, prefix=4  # type: ignore
189)
190
191
192class _Nbm(Forecast):
193    units = structs.NbmUnits(**_UNITS)
194    _service_class = NOAA_NBM  # type: ignore
195    _parser: staticmethod
196
197    async def _post_update(self) -> None:
198        self.data = self._parser(self.raw)
199
200    def _post_parse(self) -> None:
201        self.data = self._parser(self.raw)
202
203
204class Nbh(_Nbm):
205    '''
206    Class to handle NBM NBH report data
207
208    Below is typical usage for fetching and pulling NBH data for KJFK.
209
210    ```python
211    >>> from avwx import Nbh
212    >>> kjfk = Nbh("KJFK")
213    >>> kjfk.station.name
214    'John F Kennedy International Airport'
215    >>> kjfk.update()
216    True
217    >>> kjfk.last_updated
218    datetime.datetime(2020, 7, 26, 20, 37, 42, 352220, tzinfo=datetime.timezone.utc)
219    >>> print(kjfk.raw)
220    """
221    KJFK   NBM V3.2 NBH GUIDANCE    7/26/2020  1900 UTC
222    UTC  20 21 22 23 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
223    TMP  90 89 88 87 85 84 82 81 81 80 79 78 77 76 76 78 81 84 87 89 90 91 92 92 93
224    DPT  69 68 66 66 65 65 65 66 66 66 66 67 67 66 67 67 67 67 67 68 67 67 67 67 67
225    SKY   9 14 41 58 61 71 66 55 39 37 39 43 40 38 29 21 19 26 24 27 22 14 22 26 26
226    WDR  22 22 23 24 25 25 25 25 25 25 25 26 26 26 26 26 26 26 25 24 24 23 23 22 23
227    WSP  10  9  9  8  7  6  5  5  5  6  5  5  5  5  4  4  5  5  7  8  8  9 10 10 10
228    GST  17 16 16 15 14 12 11 12 12 12 12 11 11  9  9  9  9 10 11 13 14 15 16 17 17
229    P01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
230    P06                                 0                 0                 0
231    Q01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
232    DUR                                                   0
233    T01   1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
234    PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
235    PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
236    PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
237    PRA 100100100100100100100100100100100100100100100100100100100100100100100100100
238    S01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
239    SLV  99101102103105105105106105104106104104104104103102100 99 98 98 99100101102
240    I01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
241    CIG 888888888360360350340888888888888888888888888888888888888888888888888888888
242    VIS 110120120140140130120120120120110110110110110120130140150150150150150150150
243    LCB  80 60999999999999999999999999999999999999999999999999999999999999999999999
244    MHT  26 26 20 19  8  7  6  4  4  5  5  5  6  4  5  6  6 11 20 27 37 39 43 39 31
245    TWD  24 26 26 27 26 26 24 23 24 26 26 26 27 27 28 27 27 27 27 26 26 26 25 25 24
246    TWS  15 14 14 13 11 11 11 10 11 11 10 11 10  8  8  7  8  9 12 13 14 15 17 17 16
247    HID                                 6                 5                 6
248    SOL 710500430250110  0 30  0  0  0  0  0  0  0 30160330500650760830870870850720
249    """
250    >>> len(kjfk.data.forecast)
251    25
252    >>> kjfk.data.forecast[0].snow_level
253    Number(repr='99', value=9900, spoken='nine nine hundred')
254    >>> print(kjfk.data.forecast[0].solar_radiation.value, kjfk.units.solar_radiation)
255    710 W/m2
256    ```
257
258    The `parse` and `from_report` methods can parse a report string if you want
259    to override the normal fetching process.
260    '''
261
262    report_type = "nbh"
263    _parser = staticmethod(parse_nbh)
264
265
266class Nbs(_Nbm):
267    '''
268    Class to handle NBM NBS report data
269
270    Below is typical usage for fetching and pulling Nbs data for KJFK.
271
272    ```python
273    >>> from avwx import Nbs
274    >>> kjfk = Nbs("KJFK")
275    >>> kjfk.station.name
276    'John F Kennedy International Airport'
277    >>> kjfk.update()
278    True
279    >>> kjfk.last_updated
280    datetime.datetime(2020, 7, 28, 1, 3, 46, 447635, tzinfo=datetime.timezone.utc)
281    >>> print(kjfk.raw)
282    """
283    KJFK    NBM V3.2 NBS GUIDANCE    7/27/2020  2300 UTC
284    DT /JULY 28               /JULY 29                /JULY 30
285    UTC  03 06 09 12 15 18 21 00 03 06 09 12 15 18 21 00 03 06 09 12 15 18 21
286    FHR  04 07 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70
287    N/X           79          93          76          91          76
288    TMP  85 82 80 83 89 91 89 84 81 79 77 80 85 89 87 83 81 79 77 80 86 88 86
289    DPT  70 70 71 72 72 72 73 72 72 71 69 69 68 67 68 69 68 67 68 69 68 69 70
290    SKY   4 10  2  4 12 23 38 61 53 62 51 26 19  9 21 24 25 34 32 45 57 70 79
291    WDR  23 24 23 24 24 22 23 27 28 28 34 35 21 20 19 22 23 25 26 26 23 20 20
292    WSP   8  8  5  6  8  9  7  5  3  2  1  2  3  6  9  7  4  4  3  3  4  7  8
293    GST  16 15 11 11 13 15 15 11  9  5  4  4  6 12 15 13 11 11  8  6  7 13 15
294    P06      0     1    15    48    17    11     8     8     1     0     5
295    P12            1          48          17           8           1
296    Q06      0     0     0    11     0     0     0     0     0     0     0
297    Q12            0          11           0           0           0
298    DUR            0           2           0           0           0
299    T03   2  3  1  1  2 10 27 30 21 13  8  5  1  0  2  3  4  3  2  3  1  3  7
300    T12            4          48          33           6           8
301    PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
302    PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
303    PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
304    PRA 100100100100100100100100100100100100100100100100100100100100100100100
305    S06      0     0     0     0     0     0     0     0     0     0     0
306    SLV 108112113133135139141139137134124113102 99107115114118118119118118118
307    I06      0     0     0     0     0     0     0     0     0     0     0
308    CIG 888888888888888888888170888150888888888888888888888888888888888888888
309    VIS 120120110120130130130110110110110130110110110120120120110110110110110
310    LCB  60 70999 90 90999 50 60 60 60 60 60 22999999200230 70 80 60 60150 60
311    MHT   7  6  5 13 30 46 19 15  7  7 10 16 40 35 13  4  4  4  9 18 31 27 13
312    TWD  23 24 23 27 25 24 27 27 28 21 34  6 26 23 20 19 26 23 27 29 24 20 18
313    TWS  17 16  9 11 13 16 12  9  5  5  4  3  4  8 11 10  8 10 10  6  6  9 13
314    HID      4     4     4     4     3     4     4     5     5     3     4
315    SOL   0  0  0320700760360100  0  0  0320720830620190  0  0  0230480570540
316    """
317    >>> len(kjfk.data.forecast)
318    23
319    >>> kjfk.data.forecast[0].ceiling
320    Number(repr='888', value=None, spoken='unlimited')
321    >>> print(kjfk.data.forecast[7].precip_amount_12.value, kjfk.units.accumulation)
322    0.11 in
323    ```
324
325    The `parse` and `from_report` methods can parse a report string if you want
326    to override the normal fetching process.
327    '''
328
329    report_type = "nbs"
330    _parser = staticmethod(parse_nbs)
331
332
333class Nbe(_Nbm):
334    '''
335    Class to handle NBM NBE report data
336
337    Below is typical usage for fetching and pulling NBE data for KJFK.
338
339    ```python
340    >>> from avwx import Nbe
341    >>> kjfk = Nbe("KJFK")
342    >>> kjfk.station.name
343    'John F Kennedy International Airport'
344    >>> kjfk.update()
345    True
346    >>> kjfk.last_updated
347    datetime.datetime(2020, 7, 28, 1, 23, 4, 909939, tzinfo=datetime.timezone.utc)
348    >>> print(kjfk.raw)
349    """
350    KJFK    NBM V3.2 NBE GUIDANCE    7/28/2020  0000 UTC
351           WED 29| THU 30| FRI 31| SAT 01| SUN 02| MON 03| TUE 04|WED CLIMO
352    UTC    00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00
353    FHR    24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192
354    X/N    93  76| 91  76| 90  74| 86  72| 87  73| 85  74| 86  72| 84 68 83
355    TMP    84  80| 83  80| 81  78| 78  76| 78  78| 78  78| 78  76| 76
356    DPT    72  69| 68  69| 71  68| 67  66| 68  69| 70  71| 70  68| 69
357    SKY    61  21| 23  47| 80  73| 47  31| 30  54| 68  65| 66  59| 32
358    WDR    25  35| 20  26| 20   2| 16   1| 16   7| 16  24| 22  34| 18
359    WSP     5   2|  6   3|  5   4|  3   5|  7   4|  6   4|  5   4|  4
360    GST    11   4| 13   6| 13  10|  9  10| 13   7| 13   9| 16   9| 12
361    P12    48  23|  8   1| 23  28| 28  16| 18  17| 30  41| 46  31| 32 19 18
362    Q12    10   0|  0   0|  0   0|  0   0|  0   0|  0  64| 77  81| 83
363    Q24          |  0    |  0    |  0    |  0    |  0    |141    |164
364    DUR     2   1|  0   0|  0   0|  0   0|  0   0|  2  12| 12  12| 12
365    T12    46  32|  6   8| 21  22| 17   5|  6   5| 25  23| 19  18| 18
366    PZR     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
367    PSN     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
368    PPL     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
369    PRA   100 100|100 100|100 100|100 100|100 100|100 100|100 100|100
370    S12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
371    SLV   138 114|111 119|119 121|113 101|108 117|134 132|124 123|121
372    I12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
373    S24          |  0    |  0    |  0    |  0    |  0    |  0    |  0
374    SOL   100 320|190 230|270 250|360 290|370  30|190 260|250 230|450
375    """
376    >>> len(kjfk.data.forecast)
377    25
378    >>> kjfk.data.forecast[0].wind_direction
379    Number(repr='25', value=250, spoken='two five zero')
380    >>> print(kjfk.data.forecast[1].precip_duration.value, kjfk.units.duration)
381    1 hour
382    ```
383
384    The `parse` and `from_report` methods can parse a report string if you want
385    to override the normal fetching process.
386    '''
387
388    report_type = "nbe"
389    _parser = staticmethod(parse_nbe)
390
391
392class Nbx(_Nbm):
393    '''
394    Class to handle NBM NBX report data
395
396    Below is typical usage for fetching and pulling NBX data for KJFK.
397
398    ```python
399    >>> from avwx import Nbx
400    >>> kjfk = Nbx("KJFK")
401    >>> kjfk.station.name
402    'John F Kennedy International Airport'
403    >>> kjfk.update()
404    True
405    >>> kjfk.last_updated
406    datetime.datetime(2023, 10, 17, 4, 0, 0, 909939, tzinfo=datetime.timezone.utc)
407    >>> print(kjfk.raw)
408    """
409    086092  NBM V4.1 NBX GUIDANCE   10/17/2023  0300 UTC
410    WED 25 |THU 26 |FRI 27 |SAT 28
411    UTC 12 |00  12 |00  12 |00
412    FHR 201|213 225|237 249|261
413    TXN  76| 81  75| 81  75| 81
414    XND   1|  1   1|  2   1|  0
415    TMP  77| 77  77| 78  76| 78
416    TSD   1|  2   1|  1   2|  1
417    DPT  67| 67  69| 68  70| 69
418    DSD   1|  2   1|  1   2|  1
419    SKY  34| 46  27| 50  26| 37
420    SSD  12| 22  13| 22  12|  7
421    WDR   7|  7   7|  6   5|  5
422    WSP  15| 16  15| 17  15| 17
423    WSD   3|  4   3|  3   4|  3
424    GST  22| 24  22| 25  22| 25
425    GSD   2|  2   2|  1   1|  1
426    P12   8|  8   9|  7   7|  7
427    Q12   0|  0   0|  3   0|  0
428    Q24   0|      0|      3|
429    DUR   0|  0   0|  0   0|  0
430    PZR   0|  0   0|  0   0|  0
431    PSN   0|  0   0|  0   0|  0
432    PPL   0|  0   0|  0   0|  0
433    PRA   7| 16  14| 10   6| 11
434    S12   0|  0   0|  0   0|  0
435    I12   0|  0   0|  0   0|  0
436    SOL   1| 35   1| 15   1| 38
437    """
438    >>> len(kjfk.data.forecast)
439    25
440    >>> kjfk.data.forecast[0].wind_speed
441    Number(repr='15', value=150, spoken='one five zero')
442    >>> print(kjfk.data.forecast[1].solar_radiation.value, kjfk.units.solar_radiation)
443    35 W/m2
444    ```
445
446    The `parse` and `from_report` methods can parse a report string if you want
447    to override the normal fetching process.
448    '''
449
450    report_type = "nbx"
451    _parser = staticmethod(parse_nbx)
def parse_nbh(report: str) -> Optional[avwx.structs.ReportData]:
151    def parse(report: str) -> Optional[structs.ReportData]:
152        """Parser for NBM reports"""
153        if not report:
154            return None
155        data, lines = _init_parse(report)
156        lines = _trim_lines(lines, 2)
157        period_strings = _split_line(lines[hours], size, prefix)
158        timestamp = data.time.dt if data.time else None
159        periods = _find_time_periods(period_strings, timestamp)
160        data_lines = lines[hours + 1 :]
161        # Normalize line prefix length
162        if prefix != 4:
163            indexes = (4, prefix)
164            start, end = min(indexes), max(indexes)
165            data_lines = [l[:start] + l[end:] for l in data_lines]
166        _parse_lines(periods, data_lines, handle, size)
167        return data_class(  # type: ignore
168            raw=data.raw,
169            sanitized=data.sanitized,
170            station=data.station,
171            time=data.time,
172            remarks=data.remarks,
173            forecast=[period_class(**p) for p in periods],  # type: ignore
174        )

Parser for NBM reports

def parse_nbs(report: str) -> Optional[avwx.structs.ReportData]:
151    def parse(report: str) -> Optional[structs.ReportData]:
152        """Parser for NBM reports"""
153        if not report:
154            return None
155        data, lines = _init_parse(report)
156        lines = _trim_lines(lines, 2)
157        period_strings = _split_line(lines[hours], size, prefix)
158        timestamp = data.time.dt if data.time else None
159        periods = _find_time_periods(period_strings, timestamp)
160        data_lines = lines[hours + 1 :]
161        # Normalize line prefix length
162        if prefix != 4:
163            indexes = (4, prefix)
164            start, end = min(indexes), max(indexes)
165            data_lines = [l[:start] + l[end:] for l in data_lines]
166        _parse_lines(periods, data_lines, handle, size)
167        return data_class(  # type: ignore
168            raw=data.raw,
169            sanitized=data.sanitized,
170            station=data.station,
171            time=data.time,
172            remarks=data.remarks,
173            forecast=[period_class(**p) for p in periods],  # type: ignore
174        )

Parser for NBM reports

def parse_nbe(report: str) -> Optional[avwx.structs.ReportData]:
151    def parse(report: str) -> Optional[structs.ReportData]:
152        """Parser for NBM reports"""
153        if not report:
154            return None
155        data, lines = _init_parse(report)
156        lines = _trim_lines(lines, 2)
157        period_strings = _split_line(lines[hours], size, prefix)
158        timestamp = data.time.dt if data.time else None
159        periods = _find_time_periods(period_strings, timestamp)
160        data_lines = lines[hours + 1 :]
161        # Normalize line prefix length
162        if prefix != 4:
163            indexes = (4, prefix)
164            start, end = min(indexes), max(indexes)
165            data_lines = [l[:start] + l[end:] for l in data_lines]
166        _parse_lines(periods, data_lines, handle, size)
167        return data_class(  # type: ignore
168            raw=data.raw,
169            sanitized=data.sanitized,
170            station=data.station,
171            time=data.time,
172            remarks=data.remarks,
173            forecast=[period_class(**p) for p in periods],  # type: ignore
174        )

Parser for NBM reports

def parse_nbx(report: str) -> Optional[avwx.structs.ReportData]:
151    def parse(report: str) -> Optional[structs.ReportData]:
152        """Parser for NBM reports"""
153        if not report:
154            return None
155        data, lines = _init_parse(report)
156        lines = _trim_lines(lines, 2)
157        period_strings = _split_line(lines[hours], size, prefix)
158        timestamp = data.time.dt if data.time else None
159        periods = _find_time_periods(period_strings, timestamp)
160        data_lines = lines[hours + 1 :]
161        # Normalize line prefix length
162        if prefix != 4:
163            indexes = (4, prefix)
164            start, end = min(indexes), max(indexes)
165            data_lines = [l[:start] + l[end:] for l in data_lines]
166        _parse_lines(periods, data_lines, handle, size)
167        return data_class(  # type: ignore
168            raw=data.raw,
169            sanitized=data.sanitized,
170            station=data.station,
171            time=data.time,
172            remarks=data.remarks,
173            forecast=[period_class(**p) for p in periods],  # type: ignore
174        )

Parser for NBM reports

class Nbh(_Nbm):
205class Nbh(_Nbm):
206    '''
207    Class to handle NBM NBH report data
208
209    Below is typical usage for fetching and pulling NBH data for KJFK.
210
211    ```python
212    >>> from avwx import Nbh
213    >>> kjfk = Nbh("KJFK")
214    >>> kjfk.station.name
215    'John F Kennedy International Airport'
216    >>> kjfk.update()
217    True
218    >>> kjfk.last_updated
219    datetime.datetime(2020, 7, 26, 20, 37, 42, 352220, tzinfo=datetime.timezone.utc)
220    >>> print(kjfk.raw)
221    """
222    KJFK   NBM V3.2 NBH GUIDANCE    7/26/2020  1900 UTC
223    UTC  20 21 22 23 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
224    TMP  90 89 88 87 85 84 82 81 81 80 79 78 77 76 76 78 81 84 87 89 90 91 92 92 93
225    DPT  69 68 66 66 65 65 65 66 66 66 66 67 67 66 67 67 67 67 67 68 67 67 67 67 67
226    SKY   9 14 41 58 61 71 66 55 39 37 39 43 40 38 29 21 19 26 24 27 22 14 22 26 26
227    WDR  22 22 23 24 25 25 25 25 25 25 25 26 26 26 26 26 26 26 25 24 24 23 23 22 23
228    WSP  10  9  9  8  7  6  5  5  5  6  5  5  5  5  4  4  5  5  7  8  8  9 10 10 10
229    GST  17 16 16 15 14 12 11 12 12 12 12 11 11  9  9  9  9 10 11 13 14 15 16 17 17
230    P01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
231    P06                                 0                 0                 0
232    Q01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
233    DUR                                                   0
234    T01   1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
235    PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
236    PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
237    PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
238    PRA 100100100100100100100100100100100100100100100100100100100100100100100100100
239    S01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
240    SLV  99101102103105105105106105104106104104104104103102100 99 98 98 99100101102
241    I01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
242    CIG 888888888360360350340888888888888888888888888888888888888888888888888888888
243    VIS 110120120140140130120120120120110110110110110120130140150150150150150150150
244    LCB  80 60999999999999999999999999999999999999999999999999999999999999999999999
245    MHT  26 26 20 19  8  7  6  4  4  5  5  5  6  4  5  6  6 11 20 27 37 39 43 39 31
246    TWD  24 26 26 27 26 26 24 23 24 26 26 26 27 27 28 27 27 27 27 26 26 26 25 25 24
247    TWS  15 14 14 13 11 11 11 10 11 11 10 11 10  8  8  7  8  9 12 13 14 15 17 17 16
248    HID                                 6                 5                 6
249    SOL 710500430250110  0 30  0  0  0  0  0  0  0 30160330500650760830870870850720
250    """
251    >>> len(kjfk.data.forecast)
252    25
253    >>> kjfk.data.forecast[0].snow_level
254    Number(repr='99', value=9900, spoken='nine nine hundred')
255    >>> print(kjfk.data.forecast[0].solar_radiation.value, kjfk.units.solar_radiation)
256    710 W/m2
257    ```
258
259    The `parse` and `from_report` methods can parse a report string if you want
260    to override the normal fetching process.
261    '''
262
263    report_type = "nbh"
264    _parser = staticmethod(parse_nbh)

Class to handle NBM NBH report data

Below is typical usage for fetching and pulling NBH data for KJFK.

>>> from avwx import Nbh
>>> kjfk = Nbh("KJFK")
>>> kjfk.station.name
'John F Kennedy International Airport'
>>> kjfk.update()
True
>>> kjfk.last_updated
datetime.datetime(2020, 7, 26, 20, 37, 42, 352220, tzinfo=datetime.timezone.utc)
>>> print(kjfk.raw)
"""
KJFK   NBM V3.2 NBH GUIDANCE    7/26/2020  1900 UTC
UTC  20 21 22 23 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
TMP  90 89 88 87 85 84 82 81 81 80 79 78 77 76 76 78 81 84 87 89 90 91 92 92 93
DPT  69 68 66 66 65 65 65 66 66 66 66 67 67 66 67 67 67 67 67 68 67 67 67 67 67
SKY   9 14 41 58 61 71 66 55 39 37 39 43 40 38 29 21 19 26 24 27 22 14 22 26 26
WDR  22 22 23 24 25 25 25 25 25 25 25 26 26 26 26 26 26 26 25 24 24 23 23 22 23
WSP  10  9  9  8  7  6  5  5  5  6  5  5  5  5  4  4  5  5  7  8  8  9 10 10 10
GST  17 16 16 15 14 12 11 12 12 12 12 11 11  9  9  9  9 10 11 13 14 15 16 17 17
P01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
P06                                 0                 0                 0
Q01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
DUR                                                   0
T01   1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PRA 100100100100100100100100100100100100100100100100100100100100100100100100100
S01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
SLV  99101102103105105105106105104106104104104104103102100 99 98 98 99100101102
I01   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
CIG 888888888360360350340888888888888888888888888888888888888888888888888888888
VIS 110120120140140130120120120120110110110110110120130140150150150150150150150
LCB  80 60999999999999999999999999999999999999999999999999999999999999999999999
MHT  26 26 20 19  8  7  6  4  4  5  5  5  6  4  5  6  6 11 20 27 37 39 43 39 31
TWD  24 26 26 27 26 26 24 23 24 26 26 26 27 27 28 27 27 27 27 26 26 26 25 25 24
TWS  15 14 14 13 11 11 11 10 11 11 10 11 10  8  8  7  8  9 12 13 14 15 17 17 16
HID                                 6                 5                 6
SOL 710500430250110  0 30  0  0  0  0  0  0  0 30160330500650760830870870850720
"""
>>> len(kjfk.data.forecast)
25
>>> kjfk.data.forecast[0].snow_level
Number(repr='99', value=9900, spoken='nine nine hundred')
>>> print(kjfk.data.forecast[0].solar_radiation.value, kjfk.units.solar_radiation)
710 W/m2

The parse and from_report methods can parse a report string if you want to override the normal fetching process.

report_type = 'nbh'
class Nbs(_Nbm):
267class Nbs(_Nbm):
268    '''
269    Class to handle NBM NBS report data
270
271    Below is typical usage for fetching and pulling Nbs data for KJFK.
272
273    ```python
274    >>> from avwx import Nbs
275    >>> kjfk = Nbs("KJFK")
276    >>> kjfk.station.name
277    'John F Kennedy International Airport'
278    >>> kjfk.update()
279    True
280    >>> kjfk.last_updated
281    datetime.datetime(2020, 7, 28, 1, 3, 46, 447635, tzinfo=datetime.timezone.utc)
282    >>> print(kjfk.raw)
283    """
284    KJFK    NBM V3.2 NBS GUIDANCE    7/27/2020  2300 UTC
285    DT /JULY 28               /JULY 29                /JULY 30
286    UTC  03 06 09 12 15 18 21 00 03 06 09 12 15 18 21 00 03 06 09 12 15 18 21
287    FHR  04 07 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70
288    N/X           79          93          76          91          76
289    TMP  85 82 80 83 89 91 89 84 81 79 77 80 85 89 87 83 81 79 77 80 86 88 86
290    DPT  70 70 71 72 72 72 73 72 72 71 69 69 68 67 68 69 68 67 68 69 68 69 70
291    SKY   4 10  2  4 12 23 38 61 53 62 51 26 19  9 21 24 25 34 32 45 57 70 79
292    WDR  23 24 23 24 24 22 23 27 28 28 34 35 21 20 19 22 23 25 26 26 23 20 20
293    WSP   8  8  5  6  8  9  7  5  3  2  1  2  3  6  9  7  4  4  3  3  4  7  8
294    GST  16 15 11 11 13 15 15 11  9  5  4  4  6 12 15 13 11 11  8  6  7 13 15
295    P06      0     1    15    48    17    11     8     8     1     0     5
296    P12            1          48          17           8           1
297    Q06      0     0     0    11     0     0     0     0     0     0     0
298    Q12            0          11           0           0           0
299    DUR            0           2           0           0           0
300    T03   2  3  1  1  2 10 27 30 21 13  8  5  1  0  2  3  4  3  2  3  1  3  7
301    T12            4          48          33           6           8
302    PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
303    PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
304    PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
305    PRA 100100100100100100100100100100100100100100100100100100100100100100100
306    S06      0     0     0     0     0     0     0     0     0     0     0
307    SLV 108112113133135139141139137134124113102 99107115114118118119118118118
308    I06      0     0     0     0     0     0     0     0     0     0     0
309    CIG 888888888888888888888170888150888888888888888888888888888888888888888
310    VIS 120120110120130130130110110110110130110110110120120120110110110110110
311    LCB  60 70999 90 90999 50 60 60 60 60 60 22999999200230 70 80 60 60150 60
312    MHT   7  6  5 13 30 46 19 15  7  7 10 16 40 35 13  4  4  4  9 18 31 27 13
313    TWD  23 24 23 27 25 24 27 27 28 21 34  6 26 23 20 19 26 23 27 29 24 20 18
314    TWS  17 16  9 11 13 16 12  9  5  5  4  3  4  8 11 10  8 10 10  6  6  9 13
315    HID      4     4     4     4     3     4     4     5     5     3     4
316    SOL   0  0  0320700760360100  0  0  0320720830620190  0  0  0230480570540
317    """
318    >>> len(kjfk.data.forecast)
319    23
320    >>> kjfk.data.forecast[0].ceiling
321    Number(repr='888', value=None, spoken='unlimited')
322    >>> print(kjfk.data.forecast[7].precip_amount_12.value, kjfk.units.accumulation)
323    0.11 in
324    ```
325
326    The `parse` and `from_report` methods can parse a report string if you want
327    to override the normal fetching process.
328    '''
329
330    report_type = "nbs"
331    _parser = staticmethod(parse_nbs)

Class to handle NBM NBS report data

Below is typical usage for fetching and pulling Nbs data for KJFK.

>>> from avwx import Nbs
>>> kjfk = Nbs("KJFK")
>>> kjfk.station.name
'John F Kennedy International Airport'
>>> kjfk.update()
True
>>> kjfk.last_updated
datetime.datetime(2020, 7, 28, 1, 3, 46, 447635, tzinfo=datetime.timezone.utc)
>>> print(kjfk.raw)
"""
KJFK    NBM V3.2 NBS GUIDANCE    7/27/2020  2300 UTC
DT /JULY 28               /JULY 29                /JULY 30
UTC  03 06 09 12 15 18 21 00 03 06 09 12 15 18 21 00 03 06 09 12 15 18 21
FHR  04 07 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70
N/X           79          93          76          91          76
TMP  85 82 80 83 89 91 89 84 81 79 77 80 85 89 87 83 81 79 77 80 86 88 86
DPT  70 70 71 72 72 72 73 72 72 71 69 69 68 67 68 69 68 67 68 69 68 69 70
SKY   4 10  2  4 12 23 38 61 53 62 51 26 19  9 21 24 25 34 32 45 57 70 79
WDR  23 24 23 24 24 22 23 27 28 28 34 35 21 20 19 22 23 25 26 26 23 20 20
WSP   8  8  5  6  8  9  7  5  3  2  1  2  3  6  9  7  4  4  3  3  4  7  8
GST  16 15 11 11 13 15 15 11  9  5  4  4  6 12 15 13 11 11  8  6  7 13 15
P06      0     1    15    48    17    11     8     8     1     0     5
P12            1          48          17           8           1
Q06      0     0     0    11     0     0     0     0     0     0     0
Q12            0          11           0           0           0
DUR            0           2           0           0           0
T03   2  3  1  1  2 10 27 30 21 13  8  5  1  0  2  3  4  3  2  3  1  3  7
T12            4          48          33           6           8
PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
PRA 100100100100100100100100100100100100100100100100100100100100100100100
S06      0     0     0     0     0     0     0     0     0     0     0
SLV 108112113133135139141139137134124113102 99107115114118118119118118118
I06      0     0     0     0     0     0     0     0     0     0     0
CIG 888888888888888888888170888150888888888888888888888888888888888888888
VIS 120120110120130130130110110110110130110110110120120120110110110110110
LCB  60 70999 90 90999 50 60 60 60 60 60 22999999200230 70 80 60 60150 60
MHT   7  6  5 13 30 46 19 15  7  7 10 16 40 35 13  4  4  4  9 18 31 27 13
TWD  23 24 23 27 25 24 27 27 28 21 34  6 26 23 20 19 26 23 27 29 24 20 18
TWS  17 16  9 11 13 16 12  9  5  5  4  3  4  8 11 10  8 10 10  6  6  9 13
HID      4     4     4     4     3     4     4     5     5     3     4
SOL   0  0  0320700760360100  0  0  0320720830620190  0  0  0230480570540
"""
>>> len(kjfk.data.forecast)
23
>>> kjfk.data.forecast[0].ceiling
Number(repr='888', value=None, spoken='unlimited')
>>> print(kjfk.data.forecast[7].precip_amount_12.value, kjfk.units.accumulation)
0.11 in

The parse and from_report methods can parse a report string if you want to override the normal fetching process.

report_type = 'nbs'
class Nbe(_Nbm):
334class Nbe(_Nbm):
335    '''
336    Class to handle NBM NBE report data
337
338    Below is typical usage for fetching and pulling NBE data for KJFK.
339
340    ```python
341    >>> from avwx import Nbe
342    >>> kjfk = Nbe("KJFK")
343    >>> kjfk.station.name
344    'John F Kennedy International Airport'
345    >>> kjfk.update()
346    True
347    >>> kjfk.last_updated
348    datetime.datetime(2020, 7, 28, 1, 23, 4, 909939, tzinfo=datetime.timezone.utc)
349    >>> print(kjfk.raw)
350    """
351    KJFK    NBM V3.2 NBE GUIDANCE    7/28/2020  0000 UTC
352           WED 29| THU 30| FRI 31| SAT 01| SUN 02| MON 03| TUE 04|WED CLIMO
353    UTC    00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00
354    FHR    24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192
355    X/N    93  76| 91  76| 90  74| 86  72| 87  73| 85  74| 86  72| 84 68 83
356    TMP    84  80| 83  80| 81  78| 78  76| 78  78| 78  78| 78  76| 76
357    DPT    72  69| 68  69| 71  68| 67  66| 68  69| 70  71| 70  68| 69
358    SKY    61  21| 23  47| 80  73| 47  31| 30  54| 68  65| 66  59| 32
359    WDR    25  35| 20  26| 20   2| 16   1| 16   7| 16  24| 22  34| 18
360    WSP     5   2|  6   3|  5   4|  3   5|  7   4|  6   4|  5   4|  4
361    GST    11   4| 13   6| 13  10|  9  10| 13   7| 13   9| 16   9| 12
362    P12    48  23|  8   1| 23  28| 28  16| 18  17| 30  41| 46  31| 32 19 18
363    Q12    10   0|  0   0|  0   0|  0   0|  0   0|  0  64| 77  81| 83
364    Q24          |  0    |  0    |  0    |  0    |  0    |141    |164
365    DUR     2   1|  0   0|  0   0|  0   0|  0   0|  2  12| 12  12| 12
366    T12    46  32|  6   8| 21  22| 17   5|  6   5| 25  23| 19  18| 18
367    PZR     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
368    PSN     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
369    PPL     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
370    PRA   100 100|100 100|100 100|100 100|100 100|100 100|100 100|100
371    S12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
372    SLV   138 114|111 119|119 121|113 101|108 117|134 132|124 123|121
373    I12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
374    S24          |  0    |  0    |  0    |  0    |  0    |  0    |  0
375    SOL   100 320|190 230|270 250|360 290|370  30|190 260|250 230|450
376    """
377    >>> len(kjfk.data.forecast)
378    25
379    >>> kjfk.data.forecast[0].wind_direction
380    Number(repr='25', value=250, spoken='two five zero')
381    >>> print(kjfk.data.forecast[1].precip_duration.value, kjfk.units.duration)
382    1 hour
383    ```
384
385    The `parse` and `from_report` methods can parse a report string if you want
386    to override the normal fetching process.
387    '''
388
389    report_type = "nbe"
390    _parser = staticmethod(parse_nbe)

Class to handle NBM NBE report data

Below is typical usage for fetching and pulling NBE data for KJFK.

>>> from avwx import Nbe
>>> kjfk = Nbe("KJFK")
>>> kjfk.station.name
'John F Kennedy International Airport'
>>> kjfk.update()
True
>>> kjfk.last_updated
datetime.datetime(2020, 7, 28, 1, 23, 4, 909939, tzinfo=datetime.timezone.utc)
>>> print(kjfk.raw)
"""
KJFK    NBM V3.2 NBE GUIDANCE    7/28/2020  0000 UTC
       WED 29| THU 30| FRI 31| SAT 01| SUN 02| MON 03| TUE 04|WED CLIMO
UTC    00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00
FHR    24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192
X/N    93  76| 91  76| 90  74| 86  72| 87  73| 85  74| 86  72| 84 68 83
TMP    84  80| 83  80| 81  78| 78  76| 78  78| 78  78| 78  76| 76
DPT    72  69| 68  69| 71  68| 67  66| 68  69| 70  71| 70  68| 69
SKY    61  21| 23  47| 80  73| 47  31| 30  54| 68  65| 66  59| 32
WDR    25  35| 20  26| 20   2| 16   1| 16   7| 16  24| 22  34| 18
WSP     5   2|  6   3|  5   4|  3   5|  7   4|  6   4|  5   4|  4
GST    11   4| 13   6| 13  10|  9  10| 13   7| 13   9| 16   9| 12
P12    48  23|  8   1| 23  28| 28  16| 18  17| 30  41| 46  31| 32 19 18
Q12    10   0|  0   0|  0   0|  0   0|  0   0|  0  64| 77  81| 83
Q24          |  0    |  0    |  0    |  0    |  0    |141    |164
DUR     2   1|  0   0|  0   0|  0   0|  0   0|  2  12| 12  12| 12
T12    46  32|  6   8| 21  22| 17   5|  6   5| 25  23| 19  18| 18
PZR     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
PSN     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
PPL     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
PRA   100 100|100 100|100 100|100 100|100 100|100 100|100 100|100
S12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
SLV   138 114|111 119|119 121|113 101|108 117|134 132|124 123|121
I12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
S24          |  0    |  0    |  0    |  0    |  0    |  0    |  0
SOL   100 320|190 230|270 250|360 290|370  30|190 260|250 230|450
"""
>>> len(kjfk.data.forecast)
25
>>> kjfk.data.forecast[0].wind_direction
Number(repr='25', value=250, spoken='two five zero')
>>> print(kjfk.data.forecast[1].precip_duration.value, kjfk.units.duration)
1 hour

The parse and from_report methods can parse a report string if you want to override the normal fetching process.

report_type = 'nbe'
class Nbx(_Nbm):
393class Nbx(_Nbm):
394    '''
395    Class to handle NBM NBX report data
396
397    Below is typical usage for fetching and pulling NBX data for KJFK.
398
399    ```python
400    >>> from avwx import Nbx
401    >>> kjfk = Nbx("KJFK")
402    >>> kjfk.station.name
403    'John F Kennedy International Airport'
404    >>> kjfk.update()
405    True
406    >>> kjfk.last_updated
407    datetime.datetime(2023, 10, 17, 4, 0, 0, 909939, tzinfo=datetime.timezone.utc)
408    >>> print(kjfk.raw)
409    """
410    086092  NBM V4.1 NBX GUIDANCE   10/17/2023  0300 UTC
411    WED 25 |THU 26 |FRI 27 |SAT 28
412    UTC 12 |00  12 |00  12 |00
413    FHR 201|213 225|237 249|261
414    TXN  76| 81  75| 81  75| 81
415    XND   1|  1   1|  2   1|  0
416    TMP  77| 77  77| 78  76| 78
417    TSD   1|  2   1|  1   2|  1
418    DPT  67| 67  69| 68  70| 69
419    DSD   1|  2   1|  1   2|  1
420    SKY  34| 46  27| 50  26| 37
421    SSD  12| 22  13| 22  12|  7
422    WDR   7|  7   7|  6   5|  5
423    WSP  15| 16  15| 17  15| 17
424    WSD   3|  4   3|  3   4|  3
425    GST  22| 24  22| 25  22| 25
426    GSD   2|  2   2|  1   1|  1
427    P12   8|  8   9|  7   7|  7
428    Q12   0|  0   0|  3   0|  0
429    Q24   0|      0|      3|
430    DUR   0|  0   0|  0   0|  0
431    PZR   0|  0   0|  0   0|  0
432    PSN   0|  0   0|  0   0|  0
433    PPL   0|  0   0|  0   0|  0
434    PRA   7| 16  14| 10   6| 11
435    S12   0|  0   0|  0   0|  0
436    I12   0|  0   0|  0   0|  0
437    SOL   1| 35   1| 15   1| 38
438    """
439    >>> len(kjfk.data.forecast)
440    25
441    >>> kjfk.data.forecast[0].wind_speed
442    Number(repr='15', value=150, spoken='one five zero')
443    >>> print(kjfk.data.forecast[1].solar_radiation.value, kjfk.units.solar_radiation)
444    35 W/m2
445    ```
446
447    The `parse` and `from_report` methods can parse a report string if you want
448    to override the normal fetching process.
449    '''
450
451    report_type = "nbx"
452    _parser = staticmethod(parse_nbx)

Class to handle NBM NBX report data

Below is typical usage for fetching and pulling NBX data for KJFK.

>>> from avwx import Nbx
>>> kjfk = Nbx("KJFK")
>>> kjfk.station.name
'John F Kennedy International Airport'
>>> kjfk.update()
True
>>> kjfk.last_updated
datetime.datetime(2023, 10, 17, 4, 0, 0, 909939, tzinfo=datetime.timezone.utc)
>>> print(kjfk.raw)
"""
086092  NBM V4.1 NBX GUIDANCE   10/17/2023  0300 UTC
WED 25 |THU 26 |FRI 27 |SAT 28
UTC 12 |00  12 |00  12 |00
FHR 201|213 225|237 249|261
TXN  76| 81  75| 81  75| 81
XND   1|  1   1|  2   1|  0
TMP  77| 77  77| 78  76| 78
TSD   1|  2   1|  1   2|  1
DPT  67| 67  69| 68  70| 69
DSD   1|  2   1|  1   2|  1
SKY  34| 46  27| 50  26| 37
SSD  12| 22  13| 22  12|  7
WDR   7|  7   7|  6   5|  5
WSP  15| 16  15| 17  15| 17
WSD   3|  4   3|  3   4|  3
GST  22| 24  22| 25  22| 25
GSD   2|  2   2|  1   1|  1
P12   8|  8   9|  7   7|  7
Q12   0|  0   0|  3   0|  0
Q24   0|      0|      3|
DUR   0|  0   0|  0   0|  0
PZR   0|  0   0|  0   0|  0
PSN   0|  0   0|  0   0|  0
PPL   0|  0   0|  0   0|  0
PRA   7| 16  14| 10   6| 11
S12   0|  0   0|  0   0|  0
I12   0|  0   0|  0   0|  0
SOL   1| 35   1| 15   1| 38
"""
>>> len(kjfk.data.forecast)
25
>>> kjfk.data.forecast[0].wind_speed
Number(repr='15', value=150, spoken='one five zero')
>>> print(kjfk.data.forecast[1].solar_radiation.value, kjfk.units.solar_radiation)
35 W/m2

The parse and from_report methods can parse a report string if you want to override the normal fetching process.

report_type = 'nbx'