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

Parser for NBM reports.

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

Parser for NBM reports.

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

Parser for NBM reports.

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

Parser for NBM reports.

class Nbh(_Nbm):
221class Nbh(_Nbm):
222    '''
223    Class to handle NBM NBH report data
224
225    Below is typical usage for fetching and pulling NBH data for KJFK.
226
227    ```python
228    >>> from avwx import Nbh
229    >>> kjfk = Nbh("KJFK")
230    >>> kjfk.station.name
231    'John F Kennedy International Airport'
232    >>> kjfk.update()
233    True
234    >>> kjfk.last_updated
235    datetime.datetime(2020, 7, 26, 20, 37, 42, 352220, tzinfo=datetime.timezone.utc)
236    >>> print(kjfk.raw)
237    """
238    KJFK   NBM V3.2 NBH GUIDANCE    7/26/2020  1900 UTC
239    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
240    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
241    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
242    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
243    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
244    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
245    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
246    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
247    P06                                 0                 0                 0
248    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
249    DUR                                                   0
250    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
251    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
252    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
253    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
254    PRA 100100100100100100100100100100100100100100100100100100100100100100100100100
255    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
256    SLV  99101102103105105105106105104106104104104104103102100 99 98 98 99100101102
257    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
258    CIG 888888888360360350340888888888888888888888888888888888888888888888888888888
259    VIS 110120120140140130120120120120110110110110110120130140150150150150150150150
260    LCB  80 60999999999999999999999999999999999999999999999999999999999999999999999
261    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
262    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
263    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
264    HID                                 6                 5                 6
265    SOL 710500430250110  0 30  0  0  0  0  0  0  0 30160330500650760830870870850720
266    """
267    >>> len(kjfk.data.forecast)
268    25
269    >>> kjfk.data.forecast[0].snow_level
270    Number(repr='99', value=9900, spoken='nine nine hundred')
271    >>> print(kjfk.data.forecast[0].solar_radiation.value, kjfk.units.solar_radiation)
272    710 W/m2
273    ```
274
275    The `parse` and `from_report` methods can parse a report string if you want
276    to override the normal fetching process.
277    '''
278
279    report_type = "nbh"
280    _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):
283class Nbs(_Nbm):
284    '''
285    Class to handle NBM NBS report data
286
287    Below is typical usage for fetching and pulling Nbs data for KJFK.
288
289    ```python
290    >>> from avwx import Nbs
291    >>> kjfk = Nbs("KJFK")
292    >>> kjfk.station.name
293    'John F Kennedy International Airport'
294    >>> kjfk.update()
295    True
296    >>> kjfk.last_updated
297    datetime.datetime(2020, 7, 28, 1, 3, 46, 447635, tzinfo=datetime.timezone.utc)
298    >>> print(kjfk.raw)
299    """
300    KJFK    NBM V3.2 NBS GUIDANCE    7/27/2020  2300 UTC
301    DT /JULY 28               /JULY 29                /JULY 30
302    UTC  03 06 09 12 15 18 21 00 03 06 09 12 15 18 21 00 03 06 09 12 15 18 21
303    FHR  04 07 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70
304    N/X           79          93          76          91          76
305    TMP  85 82 80 83 89 91 89 84 81 79 77 80 85 89 87 83 81 79 77 80 86 88 86
306    DPT  70 70 71 72 72 72 73 72 72 71 69 69 68 67 68 69 68 67 68 69 68 69 70
307    SKY   4 10  2  4 12 23 38 61 53 62 51 26 19  9 21 24 25 34 32 45 57 70 79
308    WDR  23 24 23 24 24 22 23 27 28 28 34 35 21 20 19 22 23 25 26 26 23 20 20
309    WSP   8  8  5  6  8  9  7  5  3  2  1  2  3  6  9  7  4  4  3  3  4  7  8
310    GST  16 15 11 11 13 15 15 11  9  5  4  4  6 12 15 13 11 11  8  6  7 13 15
311    P06      0     1    15    48    17    11     8     8     1     0     5
312    P12            1          48          17           8           1
313    Q06      0     0     0    11     0     0     0     0     0     0     0
314    Q12            0          11           0           0           0
315    DUR            0           2           0           0           0
316    T03   2  3  1  1  2 10 27 30 21 13  8  5  1  0  2  3  4  3  2  3  1  3  7
317    T12            4          48          33           6           8
318    PZR   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
319    PSN   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
320    PPL   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
321    PRA 100100100100100100100100100100100100100100100100100100100100100100100
322    S06      0     0     0     0     0     0     0     0     0     0     0
323    SLV 108112113133135139141139137134124113102 99107115114118118119118118118
324    I06      0     0     0     0     0     0     0     0     0     0     0
325    CIG 888888888888888888888170888150888888888888888888888888888888888888888
326    VIS 120120110120130130130110110110110130110110110120120120110110110110110
327    LCB  60 70999 90 90999 50 60 60 60 60 60 22999999200230 70 80 60 60150 60
328    MHT   7  6  5 13 30 46 19 15  7  7 10 16 40 35 13  4  4  4  9 18 31 27 13
329    TWD  23 24 23 27 25 24 27 27 28 21 34  6 26 23 20 19 26 23 27 29 24 20 18
330    TWS  17 16  9 11 13 16 12  9  5  5  4  3  4  8 11 10  8 10 10  6  6  9 13
331    HID      4     4     4     4     3     4     4     5     5     3     4
332    SOL   0  0  0320700760360100  0  0  0320720830620190  0  0  0230480570540
333    """
334    >>> len(kjfk.data.forecast)
335    23
336    >>> kjfk.data.forecast[0].ceiling
337    Number(repr='888', value=None, spoken='unlimited')
338    >>> print(kjfk.data.forecast[7].precip_amount_12.value, kjfk.units.accumulation)
339    0.11 in
340    ```
341
342    The `parse` and `from_report` methods can parse a report string if you want
343    to override the normal fetching process.
344    '''
345
346    report_type = "nbs"
347    _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):
350class Nbe(_Nbm):
351    '''
352    Class to handle NBM NBE report data
353
354    Below is typical usage for fetching and pulling NBE data for KJFK.
355
356    ```python
357    >>> from avwx import Nbe
358    >>> kjfk = Nbe("KJFK")
359    >>> kjfk.station.name
360    'John F Kennedy International Airport'
361    >>> kjfk.update()
362    True
363    >>> kjfk.last_updated
364    datetime.datetime(2020, 7, 28, 1, 23, 4, 909939, tzinfo=datetime.timezone.utc)
365    >>> print(kjfk.raw)
366    """
367    KJFK    NBM V3.2 NBE GUIDANCE    7/28/2020  0000 UTC
368           WED 29| THU 30| FRI 31| SAT 01| SUN 02| MON 03| TUE 04|WED CLIMO
369    UTC    00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00  12| 00
370    FHR    24  36| 48  60| 72  84| 96 108|120 132|144 156|168 180|192
371    X/N    93  76| 91  76| 90  74| 86  72| 87  73| 85  74| 86  72| 84 68 83
372    TMP    84  80| 83  80| 81  78| 78  76| 78  78| 78  78| 78  76| 76
373    DPT    72  69| 68  69| 71  68| 67  66| 68  69| 70  71| 70  68| 69
374    SKY    61  21| 23  47| 80  73| 47  31| 30  54| 68  65| 66  59| 32
375    WDR    25  35| 20  26| 20   2| 16   1| 16   7| 16  24| 22  34| 18
376    WSP     5   2|  6   3|  5   4|  3   5|  7   4|  6   4|  5   4|  4
377    GST    11   4| 13   6| 13  10|  9  10| 13   7| 13   9| 16   9| 12
378    P12    48  23|  8   1| 23  28| 28  16| 18  17| 30  41| 46  31| 32 19 18
379    Q12    10   0|  0   0|  0   0|  0   0|  0   0|  0  64| 77  81| 83
380    Q24          |  0    |  0    |  0    |  0    |  0    |141    |164
381    DUR     2   1|  0   0|  0   0|  0   0|  0   0|  2  12| 12  12| 12
382    T12    46  32|  6   8| 21  22| 17   5|  6   5| 25  23| 19  18| 18
383    PZR     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
384    PSN     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
385    PPL     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
386    PRA   100 100|100 100|100 100|100 100|100 100|100 100|100 100|100
387    S12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
388    SLV   138 114|111 119|119 121|113 101|108 117|134 132|124 123|121
389    I12     0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0   0|  0
390    S24          |  0    |  0    |  0    |  0    |  0    |  0    |  0
391    SOL   100 320|190 230|270 250|360 290|370  30|190 260|250 230|450
392    """
393    >>> len(kjfk.data.forecast)
394    25
395    >>> kjfk.data.forecast[0].wind_direction
396    Number(repr='25', value=250, spoken='two five zero')
397    >>> print(kjfk.data.forecast[1].precip_duration.value, kjfk.units.duration)
398    1 hour
399    ```
400
401    The `parse` and `from_report` methods can parse a report string if you want
402    to override the normal fetching process.
403    '''
404
405    report_type = "nbe"
406    _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):
409class Nbx(_Nbm):
410    '''
411    Class to handle NBM NBX report data
412
413    Below is typical usage for fetching and pulling NBX data for KJFK.
414
415    ```python
416    >>> from avwx import Nbx
417    >>> kjfk = Nbx("KJFK")
418    >>> kjfk.station.name
419    'John F Kennedy International Airport'
420    >>> kjfk.update()
421    True
422    >>> kjfk.last_updated
423    datetime.datetime(2023, 10, 17, 4, 0, 0, 909939, tzinfo=datetime.timezone.utc)
424    >>> print(kjfk.raw)
425    """
426    086092  NBM V4.1 NBX GUIDANCE   10/17/2023  0300 UTC
427    WED 25 |THU 26 |FRI 27 |SAT 28
428    UTC 12 |00  12 |00  12 |00
429    FHR 201|213 225|237 249|261
430    TXN  76| 81  75| 81  75| 81
431    XND   1|  1   1|  2   1|  0
432    TMP  77| 77  77| 78  76| 78
433    TSD   1|  2   1|  1   2|  1
434    DPT  67| 67  69| 68  70| 69
435    DSD   1|  2   1|  1   2|  1
436    SKY  34| 46  27| 50  26| 37
437    SSD  12| 22  13| 22  12|  7
438    WDR   7|  7   7|  6   5|  5
439    WSP  15| 16  15| 17  15| 17
440    WSD   3|  4   3|  3   4|  3
441    GST  22| 24  22| 25  22| 25
442    GSD   2|  2   2|  1   1|  1
443    P12   8|  8   9|  7   7|  7
444    Q12   0|  0   0|  3   0|  0
445    Q24   0|      0|      3|
446    DUR   0|  0   0|  0   0|  0
447    PZR   0|  0   0|  0   0|  0
448    PSN   0|  0   0|  0   0|  0
449    PPL   0|  0   0|  0   0|  0
450    PRA   7| 16  14| 10   6| 11
451    S12   0|  0   0|  0   0|  0
452    I12   0|  0   0|  0   0|  0
453    SOL   1| 35   1| 15   1| 38
454    """
455    >>> len(kjfk.data.forecast)
456    25
457    >>> kjfk.data.forecast[0].wind_speed
458    Number(repr='15', value=150, spoken='one five zero')
459    >>> print(kjfk.data.forecast[1].solar_radiation.value, kjfk.units.solar_radiation)
460    35 W/m2
461    ```
462
463    The `parse` and `from_report` methods can parse a report string if you want
464    to override the normal fetching process.
465    '''
466
467    report_type = "nbx"
468    _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'