diff --git a/CODEOWNERS b/CODEOWNERS
index 71520e11acfecc7de653f64079c41d0059e295fa..3ede39518c18742181e1ced6132b4599ffde0c7f 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -190,6 +190,7 @@ homeassistant/components/notify/* @home-assistant/core
 homeassistant/components/notion/* @bachya
 homeassistant/components/nsw_fuel_station/* @nickw444
 homeassistant/components/nuki/* @pschmitt
+homeassistant/components/nws/* @MatthewFlamm
 homeassistant/components/ohmconnect/* @robbiet480
 homeassistant/components/onboarding/* @home-assistant/core
 homeassistant/components/opentherm_gw/* @mvn23
diff --git a/homeassistant/components/nws/__init__.py b/homeassistant/components/nws/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..dde2f6dee11c52222ceeb6c0ad68f0ffb797b507
--- /dev/null
+++ b/homeassistant/components/nws/__init__.py
@@ -0,0 +1 @@
+"""NWS Integration."""
diff --git a/homeassistant/components/nws/manifest.json b/homeassistant/components/nws/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..b0e5fdb208844a3009808461a2ecf29245b04176
--- /dev/null
+++ b/homeassistant/components/nws/manifest.json
@@ -0,0 +1,8 @@
+{
+    "domain": "nws",
+    "name": "National Weather Service",
+    "documentation": "https://www.home-assistant.io/components/nws",
+    "dependencies": [],
+    "codeowners": ["@MatthewFlamm"],
+    "requirements": ["pynws==0.7.4"]
+}
diff --git a/homeassistant/components/nws/weather.py b/homeassistant/components/nws/weather.py
new file mode 100644
index 0000000000000000000000000000000000000000..23cf84411a3788c25da95d6e13cb53889ef44bf3
--- /dev/null
+++ b/homeassistant/components/nws/weather.py
@@ -0,0 +1,378 @@
+"""Support for NWS weather service."""
+from collections import OrderedDict
+from datetime import timedelta
+from json import JSONDecodeError
+import logging
+
+import aiohttp
+from pynws import SimpleNWS
+import voluptuous as vol
+
+from homeassistant.components.weather import (
+    WeatherEntity,
+    PLATFORM_SCHEMA,
+    ATTR_FORECAST_CONDITION,
+    ATTR_FORECAST_TEMP,
+    ATTR_FORECAST_TIME,
+    ATTR_FORECAST_WIND_SPEED,
+    ATTR_FORECAST_WIND_BEARING,
+)
+from homeassistant.const import (
+    CONF_API_KEY,
+    CONF_NAME,
+    CONF_LATITUDE,
+    CONF_LONGITUDE,
+    CONF_MODE,
+    LENGTH_KILOMETERS,
+    LENGTH_METERS,
+    LENGTH_MILES,
+    PRESSURE_HPA,
+    PRESSURE_PA,
+    PRESSURE_INHG,
+    TEMP_CELSIUS,
+    TEMP_FAHRENHEIT,
+)
+from homeassistant.exceptions import PlatformNotReady
+from homeassistant.helpers.aiohttp_client import async_get_clientsession
+from homeassistant.helpers import config_validation as cv
+from homeassistant.util import Throttle
+from homeassistant.util.distance import convert as convert_distance
+from homeassistant.util.pressure import convert as convert_pressure
+from homeassistant.util.temperature import convert as convert_temperature
+
+_LOGGER = logging.getLogger(__name__)
+
+ATTRIBUTION = "Data from National Weather Service/NOAA"
+
+SCAN_INTERVAL = timedelta(minutes=15)
+MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5)
+
+CONF_STATION = "station"
+
+ATTR_FORECAST_DETAIL_DESCRIPTION = "detailed_description"
+ATTR_FORECAST_PRECIP_PROB = "precipitation_probability"
+ATTR_FORECAST_DAYTIME = "daytime"
+
+# Ordered so that a single condition can be chosen from multiple weather codes.
+# Catalog of NWS icon weather codes listed at:
+# https://api.weather.gov/icons
+CONDITION_CLASSES = OrderedDict(
+    [
+        (
+            "exceptional",
+            [
+                "Tornado",
+                "Hurricane conditions",
+                "Tropical storm conditions",
+                "Dust",
+                "Smoke",
+                "Haze",
+                "Hot",
+                "Cold",
+            ],
+        ),
+        ("snowy", ["Snow", "Sleet", "Blizzard"]),
+        (
+            "snowy-rainy",
+            [
+                "Rain/snow",
+                "Rain/sleet",
+                "Freezing rain/snow",
+                "Freezing rain",
+                "Rain/freezing rain",
+            ],
+        ),
+        ("hail", []),
+        (
+            "lightning-rainy",
+            [
+                "Thunderstorm (high cloud cover)",
+                "Thunderstorm (medium cloud cover)",
+                "Thunderstorm (low cloud cover)",
+            ],
+        ),
+        ("lightning", []),
+        ("pouring", []),
+        (
+            "rainy",
+            [
+                "Rain",
+                "Rain showers (high cloud cover)",
+                "Rain showers (low cloud cover)",
+            ],
+        ),
+        ("windy-variant", ["Mostly cloudy and windy", "Overcast and windy"]),
+        (
+            "windy",
+            [
+                "Fair/clear and windy",
+                "A few clouds and windy",
+                "Partly cloudy and windy",
+            ],
+        ),
+        ("fog", ["Fog/mist"]),
+        ("clear", ["Fair/clear"]),  # sunny and clear-night
+        ("cloudy", ["Mostly cloudy", "Overcast"]),
+        ("partlycloudy", ["A few clouds", "Partly cloudy"]),
+    ]
+)
+
+ERRORS = (aiohttp.ClientError, JSONDecodeError)
+
+FORECAST_MODE = ["daynight", "hourly"]
+
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
+    {
+        vol.Optional(CONF_NAME): cv.string,
+        vol.Inclusive(
+            CONF_LATITUDE, "coordinates", "Latitude and longitude must exist together"
+        ): cv.latitude,
+        vol.Inclusive(
+            CONF_LONGITUDE, "coordinates", "Latitude and longitude must exist together"
+        ): cv.longitude,
+        vol.Optional(CONF_MODE, default="daynight"): vol.In(FORECAST_MODE),
+        vol.Optional(CONF_STATION): cv.string,
+        vol.Required(CONF_API_KEY): cv.string,
+    }
+)
+
+
+def convert_condition(time, weather):
+    """
+    Convert NWS codes to HA condition.
+
+    Choose first condition in CONDITION_CLASSES that exists in weather code.
+    If no match is found, return first condition from NWS
+    """
+    conditions = [w[0] for w in weather]
+    prec_probs = [w[1] or 0 for w in weather]
+
+    # Choose condition with highest priority.
+    cond = next(
+        (
+            key
+            for key, value in CONDITION_CLASSES.items()
+            if any(condition in value for condition in conditions)
+        ),
+        conditions[0],
+    )
+
+    if cond == "clear":
+        if time == "day":
+            return "sunny", max(prec_probs)
+        if time == "night":
+            return "clear-night", max(prec_probs)
+    return cond, max(prec_probs)
+
+
+async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
+    """Set up the NWS weather platform."""
+
+    latitude = config.get(CONF_LATITUDE, hass.config.latitude)
+    longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
+    station = config.get(CONF_STATION)
+    api_key = config[CONF_API_KEY]
+    mode = config[CONF_MODE]
+
+    websession = async_get_clientsession(hass)
+    # ID request as being from HA, pynws prepends the api_key in addition
+    api_key_ha = f"{api_key} homeassistant"
+    nws = SimpleNWS(latitude, longitude, api_key_ha, mode, websession)
+
+    _LOGGER.debug("Setting up station: %s", station)
+    try:
+        await nws.set_station(station)
+    except ERRORS as status:
+        _LOGGER.error(
+            "Error getting station list for %s: %s", (latitude, longitude), status
+        )
+        raise PlatformNotReady
+
+    _LOGGER.debug("Station list: %s", nws.stations)
+    _LOGGER.debug(
+        "Initialized for coordinates %s, %s -> station %s",
+        latitude,
+        longitude,
+        nws.station,
+    )
+
+    async_add_entities([NWSWeather(nws, mode, hass.config.units, config)], True)
+
+
+class NWSWeather(WeatherEntity):
+    """Representation of a weather condition."""
+
+    def __init__(self, nws, mode, units, config):
+        """Initialise the platform with a data instance and station name."""
+        self.nws = nws
+        self.station_name = config.get(CONF_NAME, self.nws.station)
+        self.is_metric = units.is_metric
+        self.mode = mode
+
+        self.observation = None
+        self._forecast = None
+
+    @Throttle(MIN_TIME_BETWEEN_UPDATES)
+    async def async_update(self):
+        """Update Condition."""
+        _LOGGER.debug("Updating station observations %s", self.nws.station)
+        try:
+            await self.nws.update_observation()
+        except ERRORS as status:
+            _LOGGER.error(
+                "Error updating observation from station %s: %s",
+                self.nws.station,
+                status,
+            )
+        else:
+            self.observation = self.nws.observation
+        _LOGGER.debug("Updating forecast")
+        try:
+            await self.nws.update_forecast()
+        except ERRORS as status:
+            _LOGGER.error(
+                "Error updating forecast from station %s: %s", self.nws.station, status
+            )
+            return
+        self._forecast = self.nws.forecast
+
+    @property
+    def attribution(self):
+        """Return the attribution."""
+        return ATTRIBUTION
+
+    @property
+    def name(self):
+        """Return the name of the station."""
+        return self.station_name
+
+    @property
+    def temperature(self):
+        """Return the current temperature."""
+        temp_c = None
+        if self.observation:
+            temp_c = self.observation.get("temperature")
+        if temp_c:
+            return convert_temperature(temp_c, TEMP_CELSIUS, TEMP_FAHRENHEIT)
+        return None
+
+    @property
+    def pressure(self):
+        """Return the current pressure."""
+        pressure_pa = None
+        if self.observation:
+            pressure_pa = self.observation.get("seaLevelPressure")
+        if pressure_pa is None:
+            return None
+        if self.is_metric:
+            pressure = convert_pressure(pressure_pa, PRESSURE_PA, PRESSURE_HPA)
+            pressure = round(pressure)
+        else:
+            pressure = convert_pressure(pressure_pa, PRESSURE_PA, PRESSURE_INHG)
+            pressure = round(pressure, 2)
+        return pressure
+
+    @property
+    def humidity(self):
+        """Return the name of the sensor."""
+        humidity = None
+        if self.observation:
+            humidity = self.observation.get("relativeHumidity")
+        return humidity
+
+    @property
+    def wind_speed(self):
+        """Return the current windspeed."""
+        wind_m_s = None
+        if self.observation:
+            wind_m_s = self.observation.get("windSpeed")
+        if wind_m_s is None:
+            return None
+        wind_m_hr = wind_m_s * 3600
+
+        if self.is_metric:
+            wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_KILOMETERS)
+        else:
+            wind = convert_distance(wind_m_hr, LENGTH_METERS, LENGTH_MILES)
+        return round(wind)
+
+    @property
+    def wind_bearing(self):
+        """Return the current wind bearing (degrees)."""
+        wind_bearing = None
+        if self.observation:
+            wind_bearing = self.observation.get("windDirection")
+        return wind_bearing
+
+    @property
+    def temperature_unit(self):
+        """Return the unit of measurement."""
+        return TEMP_FAHRENHEIT
+
+    @property
+    def condition(self):
+        """Return current condition."""
+        weather = None
+        if self.observation:
+            weather = self.observation.get("iconWeather")
+            time = self.observation.get("iconTime")
+
+        if weather:
+            cond, _ = convert_condition(time, weather)
+            return cond
+        return None
+
+    @property
+    def visibility(self):
+        """Return visibility."""
+        vis_m = None
+        if self.observation:
+            vis_m = self.observation.get("visibility")
+        if vis_m is None:
+            return None
+
+        if self.is_metric:
+            vis = convert_distance(vis_m, LENGTH_METERS, LENGTH_KILOMETERS)
+        else:
+            vis = convert_distance(vis_m, LENGTH_METERS, LENGTH_MILES)
+        return round(vis, 0)
+
+    @property
+    def forecast(self):
+        """Return forecast."""
+        if self._forecast is None:
+            return None
+        forecast = []
+        for forecast_entry in self._forecast:
+            data = {
+                ATTR_FORECAST_DETAIL_DESCRIPTION: forecast_entry.get(
+                    "detailedForecast"
+                ),
+                ATTR_FORECAST_TEMP: forecast_entry.get("temperature"),
+                ATTR_FORECAST_TIME: forecast_entry.get("startTime"),
+            }
+
+            if self.mode == "daynight":
+                data[ATTR_FORECAST_DAYTIME] = forecast_entry.get("isDaytime")
+            time = forecast_entry.get("iconTime")
+            weather = forecast_entry.get("iconWeather")
+            if time and weather:
+                cond, precip = convert_condition(time, weather)
+            else:
+                cond, precip = None, None
+            data[ATTR_FORECAST_CONDITION] = cond
+            data[ATTR_FORECAST_PRECIP_PROB] = precip
+
+            data[ATTR_FORECAST_WIND_BEARING] = forecast_entry.get("windBearing")
+            wind_speed = forecast_entry.get("windSpeedAvg")
+            if wind_speed:
+                if self.is_metric:
+                    data[ATTR_FORECAST_WIND_SPEED] = round(
+                        convert_distance(wind_speed, LENGTH_MILES, LENGTH_KILOMETERS)
+                    )
+                else:
+                    data[ATTR_FORECAST_WIND_SPEED] = round(wind_speed)
+            else:
+                data[ATTR_FORECAST_WIND_SPEED] = None
+            forecast.append(data)
+        return forecast
diff --git a/homeassistant/components/weather/__init__.py b/homeassistant/components/weather/__init__.py
index 8f276279ee5dfe1702645cb3007a9b957988c0a8..fd122f66ac2b2f1d36d3200b7c1b801579b642e1 100644
--- a/homeassistant/components/weather/__init__.py
+++ b/homeassistant/components/weather/__init__.py
@@ -125,11 +125,11 @@ class WeatherEntity(Entity):
     @property
     def state_attributes(self):
         """Return the state attributes."""
-        data = {
-            ATTR_WEATHER_TEMPERATURE: show_temp(
+        data = {}
+        if self.temperature is not None:
+            data[ATTR_WEATHER_TEMPERATURE] = show_temp(
                 self.hass, self.temperature, self.temperature_unit, self.precision
             )
-        }
 
         humidity = self.humidity
         if humidity is not None:
diff --git a/requirements_all.txt b/requirements_all.txt
index d3d60e6a43e66e80a46427d4520c4fa4c2823057..c8e79616e17554f633117e6774f43a2cb1d691eb 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -1308,6 +1308,9 @@ pynuki==1.3.3
 # homeassistant.components.nut
 pynut2==2.1.2
 
+# homeassistant.components.nws
+pynws==0.7.4
+
 # homeassistant.components.nx584
 pynx584==0.4
 
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index b5d139719ef6de398a39234a9d871c0fda93134b..c90ad27554e2635df0934d815a6320c77a2ba676 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -294,6 +294,9 @@ pymfy==0.5.2
 # homeassistant.components.monoprice
 pymonoprice==0.3
 
+# homeassistant.components.nws
+pynws==0.7.4
+
 # homeassistant.components.nx584
 pynx584==0.4
 
diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py
index 6643fcf7aa9a35e442c8cb8a22627241a0786500..dd36771994bae2fc17d7e5a98e792933ec35d91f 100755
--- a/script/gen_requirements_all.py
+++ b/script/gen_requirements_all.py
@@ -120,6 +120,7 @@ TEST_REQUIREMENTS = (
     "pylitejet",
     "pymfy",
     "pymonoprice",
+    "pynws",
     "pynx584",
     "pyopenuv",
     "pyotp",
diff --git a/tests/components/nws/test_weather.py b/tests/components/nws/test_weather.py
new file mode 100644
index 0000000000000000000000000000000000000000..436d25750fc5188a7383ad55a1978899436fa83f
--- /dev/null
+++ b/tests/components/nws/test_weather.py
@@ -0,0 +1,274 @@
+"""Tests for the NWS weather component."""
+from homeassistant.components.nws.weather import ATTR_FORECAST_PRECIP_PROB
+from homeassistant.components.weather import (
+    ATTR_WEATHER_HUMIDITY,
+    ATTR_WEATHER_PRESSURE,
+    ATTR_WEATHER_TEMPERATURE,
+    ATTR_WEATHER_VISIBILITY,
+    ATTR_WEATHER_WIND_BEARING,
+    ATTR_WEATHER_WIND_SPEED,
+)
+from homeassistant.components.weather import (
+    ATTR_FORECAST,
+    ATTR_FORECAST_CONDITION,
+    ATTR_FORECAST_TEMP,
+    ATTR_FORECAST_TIME,
+    ATTR_FORECAST_WIND_BEARING,
+    ATTR_FORECAST_WIND_SPEED,
+)
+
+from homeassistant.const import (
+    LENGTH_KILOMETERS,
+    LENGTH_METERS,
+    LENGTH_MILES,
+    PRESSURE_INHG,
+    PRESSURE_PA,
+    PRESSURE_HPA,
+    TEMP_CELSIUS,
+    TEMP_FAHRENHEIT,
+)
+from homeassistant.util.pressure import convert as convert_pressure
+from homeassistant.util.distance import convert as convert_distance
+from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
+from homeassistant.util.temperature import convert as convert_temperature
+from homeassistant.setup import async_setup_component
+
+from tests.common import load_fixture, assert_setup_component
+
+EXP_OBS_IMP = {
+    ATTR_WEATHER_TEMPERATURE: round(
+        convert_temperature(26.7, TEMP_CELSIUS, TEMP_FAHRENHEIT)
+    ),
+    ATTR_WEATHER_WIND_BEARING: 190,
+    ATTR_WEATHER_WIND_SPEED: round(
+        convert_distance(2.6, LENGTH_METERS, LENGTH_MILES) * 3600
+    ),
+    ATTR_WEATHER_PRESSURE: round(
+        convert_pressure(101040, PRESSURE_PA, PRESSURE_INHG), 2
+    ),
+    ATTR_WEATHER_VISIBILITY: round(
+        convert_distance(16090, LENGTH_METERS, LENGTH_MILES)
+    ),
+    ATTR_WEATHER_HUMIDITY: 64,
+}
+
+EXP_OBS_METR = {
+    ATTR_WEATHER_TEMPERATURE: round(26.7),
+    ATTR_WEATHER_WIND_BEARING: 190,
+    ATTR_WEATHER_WIND_SPEED: round(
+        convert_distance(2.6, LENGTH_METERS, LENGTH_KILOMETERS) * 3600
+    ),
+    ATTR_WEATHER_PRESSURE: round(convert_pressure(101040, PRESSURE_PA, PRESSURE_HPA)),
+    ATTR_WEATHER_VISIBILITY: round(
+        convert_distance(16090, LENGTH_METERS, LENGTH_KILOMETERS)
+    ),
+    ATTR_WEATHER_HUMIDITY: 64,
+}
+
+EXP_FORE_IMP = {
+    ATTR_FORECAST_CONDITION: "lightning-rainy",
+    ATTR_FORECAST_TIME: "2019-08-12T20:00:00-04:00",
+    ATTR_FORECAST_TEMP: 70,
+    ATTR_FORECAST_WIND_SPEED: 10,
+    ATTR_FORECAST_WIND_BEARING: 180,
+    ATTR_FORECAST_PRECIP_PROB: 90,
+}
+
+EXP_FORE_METR = {
+    ATTR_FORECAST_CONDITION: "lightning-rainy",
+    ATTR_FORECAST_TIME: "2019-08-12T20:00:00-04:00",
+    ATTR_FORECAST_TEMP: round(convert_temperature(70, TEMP_FAHRENHEIT, TEMP_CELSIUS)),
+    ATTR_FORECAST_WIND_SPEED: round(
+        convert_distance(10, LENGTH_MILES, LENGTH_KILOMETERS)
+    ),
+    ATTR_FORECAST_WIND_BEARING: 180,
+    ATTR_FORECAST_PRECIP_PROB: 90,
+}
+
+
+MINIMAL_CONFIG = {
+    "weather": {
+        "platform": "nws",
+        "api_key": "x@example.com",
+        "latitude": 40.0,
+        "longitude": -85.0,
+    }
+}
+
+INVALID_CONFIG = {
+    "weather": {"platform": "nws", "api_key": "x@example.com", "latitude": 40.0}
+}
+
+STAURL = "https://api.weather.gov/points/{},{}/stations"
+OBSURL = "https://api.weather.gov/stations/{}/observations/"
+FORCURL = "https://api.weather.gov/points/{},{}/forecast"
+
+
+async def test_imperial(hass, aioclient_mock):
+    """Test with imperial units."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0), text=load_fixture("nws-weather-sta-valid.json")
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-valid.json"),
+        params={"limit": 1},
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0), text=load_fixture("nws-weather-fore-valid.json")
+    )
+
+    hass.config.units = IMPERIAL_SYSTEM
+
+    with assert_setup_component(1, "weather"):
+        await async_setup_component(hass, "weather", MINIMAL_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state
+    assert state.state == "sunny"
+
+    data = state.attributes
+    for key, value in EXP_OBS_IMP.items():
+        assert data.get(key) == value
+    assert state.attributes.get("friendly_name") == "KMIE"
+    forecast = data.get(ATTR_FORECAST)
+    for key, value in EXP_FORE_IMP.items():
+        assert forecast[0].get(key) == value
+
+
+async def test_metric(hass, aioclient_mock):
+    """Test with metric units."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0), text=load_fixture("nws-weather-sta-valid.json")
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-valid.json"),
+        params={"limit": 1},
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0), text=load_fixture("nws-weather-fore-valid.json")
+    )
+
+    hass.config.units = METRIC_SYSTEM
+
+    with assert_setup_component(1, "weather"):
+        await async_setup_component(hass, "weather", MINIMAL_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state
+    assert state.state == "sunny"
+
+    data = state.attributes
+    for key, value in EXP_OBS_METR.items():
+        assert data.get(key) == value
+    assert state.attributes.get("friendly_name") == "KMIE"
+    forecast = data.get(ATTR_FORECAST)
+    for key, value in EXP_FORE_METR.items():
+        assert forecast[0].get(key) == value
+
+
+async def test_none(hass, aioclient_mock):
+    """Test with imperial units."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0), text=load_fixture("nws-weather-sta-valid.json")
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-null.json"),
+        params={"limit": 1},
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0), text=load_fixture("nws-weather-fore-null.json")
+    )
+
+    hass.config.units = IMPERIAL_SYSTEM
+
+    with assert_setup_component(1, "weather"):
+        await async_setup_component(hass, "weather", MINIMAL_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state
+    assert state.state == "unknown"
+
+    data = state.attributes
+    for key in EXP_OBS_IMP:
+        assert data.get(key) is None
+    assert state.attributes.get("friendly_name") == "KMIE"
+    forecast = data.get(ATTR_FORECAST)
+    for key in EXP_FORE_IMP:
+        assert forecast[0].get(key) is None
+
+
+async def test_fail_obs(hass, aioclient_mock):
+    """Test failing observation/forecast update."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0), text=load_fixture("nws-weather-sta-valid.json")
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-valid.json"),
+        params={"limit": 1},
+        status=400,
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0),
+        text=load_fixture("nws-weather-fore-valid.json"),
+        status=400,
+    )
+
+    hass.config.units = IMPERIAL_SYSTEM
+
+    with assert_setup_component(1, "weather"):
+        await async_setup_component(hass, "weather", MINIMAL_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state
+
+
+async def test_fail_stn(hass, aioclient_mock):
+    """Test failing station update."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0),
+        text=load_fixture("nws-weather-sta-valid.json"),
+        status=400,
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-valid.json"),
+        params={"limit": 1},
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0), text=load_fixture("nws-weather-fore-valid.json")
+    )
+
+    hass.config.units = IMPERIAL_SYSTEM
+
+    with assert_setup_component(1, "weather"):
+        await async_setup_component(hass, "weather", MINIMAL_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state is None
+
+
+async def test_invalid_config(hass, aioclient_mock):
+    """Test invalid config.."""
+    aioclient_mock.get(
+        STAURL.format(40.0, -85.0), text=load_fixture("nws-weather-sta-valid.json")
+    )
+    aioclient_mock.get(
+        OBSURL.format("KMIE"),
+        text=load_fixture("nws-weather-obs-valid.json"),
+        params={"limit": 1},
+    )
+    aioclient_mock.get(
+        FORCURL.format(40.0, -85.0), text=load_fixture("nws-weather-fore-valid.json")
+    )
+
+    hass.config.units = IMPERIAL_SYSTEM
+
+    with assert_setup_component(0, "weather"):
+        await async_setup_component(hass, "weather", INVALID_CONFIG)
+
+    state = hass.states.get("weather.kmie")
+    assert state is None
diff --git a/tests/fixtures/nws-weather-fore-null.json b/tests/fixtures/nws-weather-fore-null.json
new file mode 100644
index 0000000000000000000000000000000000000000..6085bcdada9b0177509770dc6bd011fa5377714e
--- /dev/null
+++ b/tests/fixtures/nws-weather-fore-null.json
@@ -0,0 +1,80 @@
+{
+    "@context": [
+        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
+        {
+            "wx": "https://api.weather.gov/ontology#",
+            "geo": "http://www.opengis.net/ont/geosparql#",
+            "unit": "http://codes.wmo.int/common/unit/",
+            "@vocab": "https://api.weather.gov/ontology#"
+        }
+    ],
+    "type": "Feature",
+    "geometry": {
+        "type": "GeometryCollection",
+        "geometries": [
+            {
+                "type": "Point",
+                "coordinates": [
+                    -85.014692800000006,
+                    39.993574700000003
+                ]
+            },
+            {
+                "type": "Polygon",
+                "coordinates": [
+                    [
+                        [
+                            -85.027968599999994,
+                            40.005368300000001
+                        ],
+                        [
+                            -85.0300814,
+                            39.983399599999998
+                        ],
+                        [
+                            -85.001420100000004,
+                            39.981779299999999
+                        ],
+                        [
+                            -84.999301200000005,
+                            40.0037479
+                        ],
+                        [
+                            -85.027968599999994,
+                            40.005368300000001
+                        ]
+                    ]
+                ]
+            }
+        ]
+    },
+    "properties": {
+        "updated": "2019-08-12T23:17:40+00:00",
+        "units": "us",
+        "forecastGenerator": "BaselineForecastGenerator",
+        "generatedAt": "2019-08-13T00:33:19+00:00",
+        "updateTime": "2019-08-12T23:17:40+00:00",
+        "validTimes": "2019-08-12T17:00:00+00:00/P8DT6H",
+        "elevation": {
+            "value": 366.06479999999999,
+            "unitCode": "unit:m"
+        },
+        "periods": [
+            {
+                "number": null,
+                "name": null,
+                "startTime": null,
+                "endTime": null,
+                "isDaytime": null,
+                "temperature": null,
+                "temperatureUnit": null,
+                "temperatureTrend": null,
+                "windSpeed": null,
+                "windDirection": null,
+                "icon": null,
+                "shortForecast": null,
+                "detailedForecast": null
+            }
+        ]
+    }
+}
diff --git a/tests/fixtures/nws-weather-fore-valid.json b/tests/fixtures/nws-weather-fore-valid.json
new file mode 100644
index 0000000000000000000000000000000000000000..b3f4f4ccea8c6cc8931ebec5d00b469d4413fda4
--- /dev/null
+++ b/tests/fixtures/nws-weather-fore-valid.json
@@ -0,0 +1,80 @@
+{
+    "@context": [
+        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
+        {
+            "wx": "https://api.weather.gov/ontology#",
+            "geo": "http://www.opengis.net/ont/geosparql#",
+            "unit": "http://codes.wmo.int/common/unit/",
+            "@vocab": "https://api.weather.gov/ontology#"
+        }
+    ],
+    "type": "Feature",
+    "geometry": {
+        "type": "GeometryCollection",
+        "geometries": [
+            {
+                "type": "Point",
+                "coordinates": [
+                    -85.014692800000006,
+                    39.993574700000003
+                ]
+            },
+            {
+                "type": "Polygon",
+                "coordinates": [
+                    [
+                        [
+                            -85.027968599999994,
+                            40.005368300000001
+                        ],
+                        [
+                            -85.0300814,
+                            39.983399599999998
+                        ],
+                        [
+                            -85.001420100000004,
+                            39.981779299999999
+                        ],
+                        [
+                            -84.999301200000005,
+                            40.0037479
+                        ],
+                        [
+                            -85.027968599999994,
+                            40.005368300000001
+                        ]
+                    ]
+                ]
+            }
+        ]
+    },
+    "properties": {
+        "updated": "2019-08-12T23:17:40+00:00",
+        "units": "us",
+        "forecastGenerator": "BaselineForecastGenerator",
+        "generatedAt": "2019-08-13T00:33:19+00:00",
+        "updateTime": "2019-08-12T23:17:40+00:00",
+        "validTimes": "2019-08-12T17:00:00+00:00/P8DT6H",
+        "elevation": {
+            "value": 366.06479999999999,
+            "unitCode": "unit:m"
+        },
+        "periods": [
+            {
+                "number": 1,
+                "name": "Tonight",
+                "startTime": "2019-08-12T20:00:00-04:00",
+                "endTime": "2019-08-13T06:00:00-04:00",
+                "isDaytime": false,
+                "temperature": 70,
+                "temperatureUnit": "F",
+                "temperatureTrend": null,
+                "windSpeed": "7 to 13 mph",
+                "windDirection": "S",
+                "icon": "https://api.weather.gov/icons/land/night/tsra,40/tsra,90?size=medium",
+                "shortForecast": "Showers And Thunderstorms",
+                "detailedForecast": "A detailed forecast."
+            }
+        ]
+    }
+}
diff --git a/tests/fixtures/nws-weather-obs-null.json b/tests/fixtures/nws-weather-obs-null.json
new file mode 100644
index 0000000000000000000000000000000000000000..36ae66283e502ffdf6776d918369c0fd38224fa2
--- /dev/null
+++ b/tests/fixtures/nws-weather-obs-null.json
@@ -0,0 +1,161 @@
+{
+    "@context": [
+        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
+        {
+            "wx": "https://api.weather.gov/ontology#",
+            "s": "https://schema.org/",
+            "geo": "http://www.opengis.net/ont/geosparql#",
+            "unit": "http://codes.wmo.int/common/unit/",
+            "@vocab": "https://api.weather.gov/ontology#",
+            "geometry": {
+                "@id": "s:GeoCoordinates",
+                "@type": "geo:wktLiteral"
+            },
+            "city": "s:addressLocality",
+            "state": "s:addressRegion",
+            "distance": {
+                "@id": "s:Distance",
+                "@type": "s:QuantitativeValue"
+            },
+            "bearing": {
+                "@type": "s:QuantitativeValue"
+            },
+            "value": {
+                "@id": "s:value"
+            },
+            "unitCode": {
+                "@id": "s:unitCode",
+                "@type": "@id"
+            },
+            "forecastOffice": {
+                "@type": "@id"
+            },
+            "forecastGridData": {
+                "@type": "@id"
+            },
+            "publicZone": {
+                "@type": "@id"
+            },
+            "county": {
+                "@type": "@id"
+            }
+        }
+    ],
+    "type": "FeatureCollection",
+    "features": [
+        {
+            "id": "https://api.weather.gov/stations/KMIE/observations/2019-08-12T23:53:00+00:00",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.400000000000006,
+                    40.25
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMIE/observations/2019-08-12T23:53:00+00:00",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 286,
+                    "unitCode": "unit:m"
+                },
+                "station": "https://api.weather.gov/stations/KMIE",
+                "timestamp": "2019-08-12T23:53:00+00:00",
+                "rawMessage": null,
+                "textDescription": "Clear",
+                "icon": null,
+                "presentWeather": [],
+                "temperature": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "dewpoint": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "windDirection": {
+                    "value": null,
+                    "unitCode": "unit:degree_(angle)",
+                    "qualityControl": "qc:V"
+                },
+                "windSpeed": {
+                    "value": null,
+                    "unitCode": "unit:m_s-1",
+                    "qualityControl": "qc:V"
+                },
+                "windGust": {
+                    "value": null,
+                    "unitCode": "unit:m_s-1",
+                    "qualityControl": "qc:Z"
+                },
+                "barometricPressure": {
+                    "value": null,
+                    "unitCode": "unit:Pa",
+                    "qualityControl": "qc:V"
+                },
+                "seaLevelPressure": {
+                    "value": null,
+                    "unitCode": "unit:Pa",
+                    "qualityControl": "qc:V"
+                },
+                "visibility": {
+                    "value": null,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:C"
+                },
+                "maxTemperatureLast24Hours": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": null
+                },
+                "minTemperatureLast24Hours": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": null
+                },
+                "precipitationLastHour": {
+                    "value": null,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:Z"
+                },
+                "precipitationLast3Hours": {
+                    "value": null,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:Z"
+                },
+                "precipitationLast6Hours": {
+                    "value": 0,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:C"
+                },
+                "relativeHumidity": {
+                    "value": null,
+                    "unitCode": "unit:percent",
+                    "qualityControl": "qc:C"
+                },
+                "windChill": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "heatIndex": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "cloudLayers": [
+                    {
+                        "base": {
+                            "value": null,
+                            "unitCode": "unit:m"
+                        },
+                        "amount": "CLR"
+                    }
+                ]
+            }
+        }
+    ]
+}
diff --git a/tests/fixtures/nws-weather-obs-valid.json b/tests/fixtures/nws-weather-obs-valid.json
new file mode 100644
index 0000000000000000000000000000000000000000..a6d307fc9b13f2dd9447dc298c5fb7abe6482bcc
--- /dev/null
+++ b/tests/fixtures/nws-weather-obs-valid.json
@@ -0,0 +1,161 @@
+{
+    "@context": [
+        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
+        {
+            "wx": "https://api.weather.gov/ontology#",
+            "s": "https://schema.org/",
+            "geo": "http://www.opengis.net/ont/geosparql#",
+            "unit": "http://codes.wmo.int/common/unit/",
+            "@vocab": "https://api.weather.gov/ontology#",
+            "geometry": {
+                "@id": "s:GeoCoordinates",
+                "@type": "geo:wktLiteral"
+            },
+            "city": "s:addressLocality",
+            "state": "s:addressRegion",
+            "distance": {
+                "@id": "s:Distance",
+                "@type": "s:QuantitativeValue"
+            },
+            "bearing": {
+                "@type": "s:QuantitativeValue"
+            },
+            "value": {
+                "@id": "s:value"
+            },
+            "unitCode": {
+                "@id": "s:unitCode",
+                "@type": "@id"
+            },
+            "forecastOffice": {
+                "@type": "@id"
+            },
+            "forecastGridData": {
+                "@type": "@id"
+            },
+            "publicZone": {
+                "@type": "@id"
+            },
+            "county": {
+                "@type": "@id"
+            }
+        }
+    ],
+    "type": "FeatureCollection",
+    "features": [
+        {
+            "id": "https://api.weather.gov/stations/KMIE/observations/2019-08-12T23:53:00+00:00",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.400000000000006,
+                    40.25
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMIE/observations/2019-08-12T23:53:00+00:00",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 286,
+                    "unitCode": "unit:m"
+                },
+                "station": "https://api.weather.gov/stations/KMIE",
+                "timestamp": "2019-08-12T23:53:00+00:00",
+                "rawMessage": "KMIE 122353Z 19005KT 10SM CLR 27/19 A2987 RMK AO2 SLP104 60000 T02670194 10272 20250 58002",
+                "textDescription": "Clear",
+                "icon": "https://api.weather.gov/icons/land/day/skc?size=medium",
+                "presentWeather": [],
+                "temperature": {
+                    "value": 26.700000000000045,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "dewpoint": {
+                    "value": 19.400000000000034,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "windDirection": {
+                    "value": 190,
+                    "unitCode": "unit:degree_(angle)",
+                    "qualityControl": "qc:V"
+                },
+                "windSpeed": {
+                    "value": 2.6000000000000001,
+                    "unitCode": "unit:m_s-1",
+                    "qualityControl": "qc:V"
+                },
+                "windGust": {
+                    "value": null,
+                    "unitCode": "unit:m_s-1",
+                    "qualityControl": "qc:Z"
+                },
+                "barometricPressure": {
+                    "value": 101150,
+                    "unitCode": "unit:Pa",
+                    "qualityControl": "qc:V"
+                },
+                "seaLevelPressure": {
+                    "value": 101040,
+                    "unitCode": "unit:Pa",
+                    "qualityControl": "qc:V"
+                },
+                "visibility": {
+                    "value": 16090,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:C"
+                },
+                "maxTemperatureLast24Hours": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": null
+                },
+                "minTemperatureLast24Hours": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": null
+                },
+                "precipitationLastHour": {
+                    "value": null,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:Z"
+                },
+                "precipitationLast3Hours": {
+                    "value": null,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:Z"
+                },
+                "precipitationLast6Hours": {
+                    "value": 0,
+                    "unitCode": "unit:m",
+                    "qualityControl": "qc:C"
+                },
+                "relativeHumidity": {
+                    "value": 64.292485914891955,
+                    "unitCode": "unit:percent",
+                    "qualityControl": "qc:C"
+                },
+                "windChill": {
+                    "value": null,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "heatIndex": {
+                    "value": 27.981288713580284,
+                    "unitCode": "unit:degC",
+                    "qualityControl": "qc:V"
+                },
+                "cloudLayers": [
+                    {
+                        "base": {
+                            "value": null,
+                            "unitCode": "unit:m"
+                        },
+                        "amount": "CLR"
+                    }
+                ]
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/tests/fixtures/nws-weather-sta-valid.json b/tests/fixtures/nws-weather-sta-valid.json
new file mode 100644
index 0000000000000000000000000000000000000000..b4fe086366c8fb611b4480fe5624e16a8906e168
--- /dev/null
+++ b/tests/fixtures/nws-weather-sta-valid.json
@@ -0,0 +1,996 @@
+{
+    "@context": [
+        "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
+        {
+            "wx": "https://api.weather.gov/ontology#",
+            "s": "https://schema.org/",
+            "geo": "http://www.opengis.net/ont/geosparql#",
+            "unit": "http://codes.wmo.int/common/unit/",
+            "@vocab": "https://api.weather.gov/ontology#",
+            "geometry": {
+                "@id": "s:GeoCoordinates",
+                "@type": "geo:wktLiteral"
+            },
+            "city": "s:addressLocality",
+            "state": "s:addressRegion",
+            "distance": {
+                "@id": "s:Distance",
+                "@type": "s:QuantitativeValue"
+            },
+            "bearing": {
+                "@type": "s:QuantitativeValue"
+            },
+            "value": {
+                "@id": "s:value"
+            },
+            "unitCode": {
+                "@id": "s:unitCode",
+                "@type": "@id"
+            },
+            "forecastOffice": {
+                "@type": "@id"
+            },
+            "forecastGridData": {
+                "@type": "@id"
+            },
+            "publicZone": {
+                "@type": "@id"
+            },
+            "county": {
+                "@type": "@id"
+            },
+            "observationStations": {
+                "@container": "@list",
+                "@type": "@id"
+            }
+        }
+    ],
+    "type": "FeatureCollection",
+    "features": [
+        {
+            "id": "https://api.weather.gov/stations/KMIE",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.393609999999995,
+                    40.234169999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMIE",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 284.988,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KMIE",
+                "name": "Muncie, Delaware County-Johnson Field",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KVES",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.531899899999999,
+                    40.2044
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KVES",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 306.93360000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KVES",
+                "name": "Versailles Darke County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KAID",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.609769999999997,
+                    40.106119999999997
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KAID",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 276.14879999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KAID",
+                "name": "Anderson Municipal Airport",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KDAY",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.218609999999998,
+                    39.906109999999998
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KDAY",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 306.93360000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KDAY",
+                "name": "Dayton, Cox Dayton International Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KGEZ",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.799819999999997,
+                    39.585459999999998
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KGEZ",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 244.1448,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KGEZ",
+                "name": "Shelbyville Municipal Airport",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KMGY",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.224720000000005,
+                    39.588889999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMGY",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 291.9984,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KMGY",
+                "name": "Dayton, Dayton-Wright Brothers Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KHAO",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.520610000000005,
+                    39.36121
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KHAO",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 185.0136,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KHAO",
+                "name": "Butler County Regional Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KFFO",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.049999999999997,
+                    39.833329900000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KFFO",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 250.85040000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KFFO",
+                "name": "Dayton / Wright-Patterson Air Force Base",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KCVG",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.672290000000004,
+                    39.044559999999997
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KCVG",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 262.12799999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KCVG",
+                "name": "Cincinnati/Northern Kentucky International Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KEDJ",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.819199999999995,
+                    40.372300000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KEDJ",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 341.98560000000003,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KEDJ",
+                "name": "Bellefontaine Regional Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KFWA",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.206370000000007,
+                    40.97251
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KFWA",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 242.9256,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KFWA",
+                "name": "Fort Wayne International Airport",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KBAK",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.900000000000006,
+                    39.266669999999998
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KBAK",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 199.94880000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KBAK",
+                "name": "Columbus / Bakalar",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KEYE",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -86.295829999999995,
+                    39.825000000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KEYE",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 249.93600000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KEYE",
+                "name": "Indianapolis, Eagle Creek Airpark",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KLUK",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.41583,
+                    39.105829999999997
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KLUK",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 146.9136,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KLUK",
+                "name": "Cincinnati, Cincinnati Municipal Airport Lunken Field",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KIND",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -86.281599999999997,
+                    39.725180000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KIND",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 240.792,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KIND",
+                "name": "Indianapolis International Airport",
+                "timeZone": "America/Indiana/Indianapolis"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KAOH",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.021389999999997,
+                    40.708060000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KAOH",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 296.87520000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KAOH",
+                "name": "Lima, Lima Allen County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KI69",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.2102,
+                    39.078400000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KI69",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 256.94640000000004,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KI69",
+                "name": "Batavia Clermont County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KILN",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.779169899999999,
+                    39.428330000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KILN",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 327.96480000000003,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KILN",
+                "name": "Wilmington, Airborne Airpark Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KMRT",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.351600000000005,
+                    40.224699999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMRT",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 311.20080000000002,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KMRT",
+                "name": "Marysville Union County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KTZR",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.137219999999999,
+                    39.900829999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KTZR",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 276.14879999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KTZR",
+                "name": "Columbus, Bolton Field Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KFDY",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.668610000000001,
+                    41.01361
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KFDY",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 248.10720000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KFDY",
+                "name": "Findlay, Findlay Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KDLZ",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.114800000000002,
+                    40.279699999999998
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KDLZ",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 288.036,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KDLZ",
+                "name": "Delaware Municipal Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KOSU",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.0780599,
+                    40.078060000000001
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KOSU",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 274.92959999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KOSU",
+                "name": "Columbus, Ohio State University Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KLCK",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.933329999999998,
+                    39.816670000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KLCK",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 227.07600000000002,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KLCK",
+                "name": "Rickenbacker Air National Guard Base",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KMNN",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.068330000000003,
+                    40.616669999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMNN",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 302.97120000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KMNN",
+                "name": "Marion, Marion Municipal Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KCMH",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.876390000000001,
+                    39.994999999999997
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KCMH",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 248.10720000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KCMH",
+                "name": "Columbus - John Glenn Columbus International Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KFGX",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -83.743399999999994,
+                    38.541800000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KFGX",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 277.9776,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KFGX",
+                "name": "Flemingsburg Fleming-Mason Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KFFT",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.903329999999997,
+                    38.184719999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KFFT",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 245.0592,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KFFT",
+                "name": "Frankfort, Capital City Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KLHQ",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.663330000000002,
+                    39.757219900000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KLHQ",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 263.95679999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KLHQ",
+                "name": "Lancaster, Fairfield County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KLOU",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.663610000000006,
+                    38.227780000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KLOU",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 166.11600000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KLOU",
+                "name": "Louisville, Bowman Field Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KSDF",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -85.72972,
+                    38.177219999999998
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KSDF",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 150.876,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KSDF",
+                "name": "Louisville, Standiford Field",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KVTA",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.462500000000006,
+                    40.022779999999997
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KVTA",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 269.13839999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KVTA",
+                "name": "Newark, Newark Heath Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KLEX",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -84.6114599,
+                    38.033900000000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KLEX",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 291.084,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KLEX",
+                "name": "Lexington Blue Grass Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KMFD",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.517780000000002,
+                    40.820279900000003
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KMFD",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 395.02080000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KMFD",
+                "name": "Mansfield - Mansfield Lahm Regional Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KZZV",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.892219999999995,
+                    39.94444
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KZZV",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 274.01519999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KZZV",
+                "name": "Zanesville, Zanesville Municipal Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KHTS",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -82.555000000000007,
+                    38.365000000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KHTS",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 252.06960000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KHTS",
+                "name": "Huntington, Tri-State Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KBJJ",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.886669999999995,
+                    40.873060000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KBJJ",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 345.94800000000004,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KBJJ",
+                "name": "Wooster, Wayne County Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KPHD",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.423609999999996,
+                    40.471939900000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KPHD",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 271.88159999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KPHD",
+                "name": "New Philadelphia, Harry Clever Field",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KPKB",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.439170000000004,
+                    39.344999999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KPKB",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 262.12799999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KPKB",
+                "name": "Parkersburg, Mid-Ohio Valley Regional Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KCAK",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.443430000000006,
+                    40.918109999999999
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KCAK",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 369.11279999999999,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KCAK",
+                "name": "Akron Canton Regional Airport",
+                "timeZone": "America/New_York"
+            }
+        },
+        {
+            "id": "https://api.weather.gov/stations/KCRW",
+            "type": "Feature",
+            "geometry": {
+                "type": "Point",
+                "coordinates": [
+                    -81.591390000000004,
+                    38.379440000000002
+                ]
+            },
+            "properties": {
+                "@id": "https://api.weather.gov/stations/KCRW",
+                "@type": "wx:ObservationStation",
+                "elevation": {
+                    "value": 299.00880000000001,
+                    "unitCode": "unit:m"
+                },
+                "stationIdentifier": "KCRW",
+                "name": "Charleston, Yeager Airport",
+                "timeZone": "America/New_York"
+            }
+        }
+    ],
+    "observationStations": [
+        "https://api.weather.gov/stations/KMIE",
+        "https://api.weather.gov/stations/KVES",
+        "https://api.weather.gov/stations/KAID",
+        "https://api.weather.gov/stations/KDAY",
+        "https://api.weather.gov/stations/KGEZ",
+        "https://api.weather.gov/stations/KMGY",
+        "https://api.weather.gov/stations/KHAO",
+        "https://api.weather.gov/stations/KFFO",
+        "https://api.weather.gov/stations/KCVG",
+        "https://api.weather.gov/stations/KEDJ",
+        "https://api.weather.gov/stations/KFWA",
+        "https://api.weather.gov/stations/KBAK",
+        "https://api.weather.gov/stations/KEYE",
+        "https://api.weather.gov/stations/KLUK",
+        "https://api.weather.gov/stations/KIND",
+        "https://api.weather.gov/stations/KAOH",
+        "https://api.weather.gov/stations/KI69",
+        "https://api.weather.gov/stations/KILN",
+        "https://api.weather.gov/stations/KMRT",
+        "https://api.weather.gov/stations/KTZR",
+        "https://api.weather.gov/stations/KFDY",
+        "https://api.weather.gov/stations/KDLZ",
+        "https://api.weather.gov/stations/KOSU",
+        "https://api.weather.gov/stations/KLCK",
+        "https://api.weather.gov/stations/KMNN",
+        "https://api.weather.gov/stations/KCMH",
+        "https://api.weather.gov/stations/KFGX",
+        "https://api.weather.gov/stations/KFFT",
+        "https://api.weather.gov/stations/KLHQ",
+        "https://api.weather.gov/stations/KLOU",
+        "https://api.weather.gov/stations/KSDF",
+        "https://api.weather.gov/stations/KVTA",
+        "https://api.weather.gov/stations/KLEX",
+        "https://api.weather.gov/stations/KMFD",
+        "https://api.weather.gov/stations/KZZV",
+        "https://api.weather.gov/stations/KHTS",
+        "https://api.weather.gov/stations/KBJJ",
+        "https://api.weather.gov/stations/KPHD",
+        "https://api.weather.gov/stations/KPKB",
+        "https://api.weather.gov/stations/KCAK",
+        "https://api.weather.gov/stations/KCRW"
+    ]
+}
\ No newline at end of file