mirror of
https://github.com/home-assistant/core.git
synced 2025-08-14 18:11:41 +02:00
Add metar fallback.
Use metar code from nws observation if normal api is missing data.
This commit is contained in:
@@ -4,5 +4,8 @@
|
||||
"documentation": "https://www.home-assistant.io/components/nws",
|
||||
"dependencies": [],
|
||||
"codeowners": ["@MatthewFlamm"],
|
||||
"requirements": ["pynws==0.6"]
|
||||
"requirements": [
|
||||
"pynws==0.6",
|
||||
"metar==1.7.0"
|
||||
]
|
||||
}
|
||||
|
@@ -22,8 +22,6 @@ 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
|
||||
|
||||
REQUIREMENTS = ['pynws==0.6']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTRIBUTION = 'Data from National Weather Service/NOAA'
|
||||
@@ -127,7 +125,7 @@ async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the NWS weather platform."""
|
||||
from pynws import Nws
|
||||
|
||||
from metar import Metar
|
||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
station = config.get(CONF_STATION)
|
||||
@@ -155,16 +153,21 @@ async def async_setup_platform(hass, config, async_add_entities,
|
||||
nws.station = station
|
||||
_LOGGER.debug("Initialized station %s", station[0])
|
||||
|
||||
async_add_entities([NWSWeather(nws, hass.config.units, config)], True)
|
||||
async_add_entities(
|
||||
[NWSWeather(nws, Metar.Metar, hass.config.units, config)],
|
||||
True)
|
||||
|
||||
|
||||
class NWSWeather(WeatherEntity):
|
||||
"""Representation of a weather condition."""
|
||||
|
||||
def __init__(self, nws, units, config):
|
||||
def __init__(self, nws, metar, units, config):
|
||||
"""Initialise the platform with a data instance and station name."""
|
||||
self._nws = nws
|
||||
self._metar = metar
|
||||
self._station_name = config.get(CONF_NAME, self._nws.station)
|
||||
|
||||
self._metar_obs = None
|
||||
self._observation = None
|
||||
self._forecast = None
|
||||
self._description = None
|
||||
@@ -178,6 +181,11 @@ class NWSWeather(WeatherEntity):
|
||||
_LOGGER.debug("Updating station observations %s",
|
||||
self._nws.station)
|
||||
self._observation = await self._nws.observations()
|
||||
self._metar_obs = [
|
||||
self._metar(obs['rawMessage'])
|
||||
for obs in self._observation
|
||||
if 'rawMessage' in obs.keys()
|
||||
]
|
||||
_LOGGER.debug("Updating forecast")
|
||||
if self._mode == 'daynight':
|
||||
self._forecast = await self._nws.forecast()
|
||||
@@ -200,6 +208,8 @@ class NWSWeather(WeatherEntity):
|
||||
def temperature(self):
|
||||
"""Return the current temperature."""
|
||||
temp_c = self._observation[0]['temperature']['value']
|
||||
if temp_c is None and self._metar_obs:
|
||||
temp_c = self._metar_obs[0].temp.value(units='C')
|
||||
if temp_c is not None:
|
||||
return convert_temperature(temp_c, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||
return None
|
||||
@@ -208,9 +218,13 @@ class NWSWeather(WeatherEntity):
|
||||
def pressure(self):
|
||||
"""Return the current pressure."""
|
||||
pressure_pa = self._observation[0]['seaLevelPressure']['value']
|
||||
# convert Pa to in Hg
|
||||
if pressure_pa is None:
|
||||
return None
|
||||
|
||||
if pressure_pa is None and self._metar_obs:
|
||||
pressure_hpa = self._metar_obs[0].press.value(units='HPA')
|
||||
if pressure_hpa is None:
|
||||
return None
|
||||
pressure_pa = convert_pressure(pressure_hpa, PRESSURE_HPA,
|
||||
PRESSURE_PA)
|
||||
|
||||
if self._is_metric:
|
||||
pressure = convert_pressure(pressure_pa, PRESSURE_PA, PRESSURE_HPA)
|
||||
@@ -230,6 +244,9 @@ class NWSWeather(WeatherEntity):
|
||||
def wind_speed(self):
|
||||
"""Return the current windspeed."""
|
||||
wind_m_s = self._observation[0]['windSpeed']['value']
|
||||
if wind_m_s is None and self._metar_obs:
|
||||
wind_m_s = self._metar_obs[0].wind_speed.value(units='MPS')
|
||||
print(wind_m_s)
|
||||
if wind_m_s is None:
|
||||
return None
|
||||
wind_m_hr = wind_m_s * 3600
|
||||
@@ -244,7 +261,10 @@ class NWSWeather(WeatherEntity):
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the current wind bearing (degrees)."""
|
||||
return self._observation[0]['windDirection']['value']
|
||||
wind_bearing = self._observation[0]['windDirection']['value']
|
||||
if wind_bearing is None and self._metar_obs:
|
||||
wind_bearing = self._metar_obs[0].wind_dir.value()
|
||||
return wind_bearing
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
@@ -262,6 +282,8 @@ class NWSWeather(WeatherEntity):
|
||||
def visibility(self):
|
||||
"""Return visibility."""
|
||||
vis_m = self._observation[0]['visibility']['value']
|
||||
if vis_m is None and self._metar_obs:
|
||||
vis_m = self._metar_obs[0].vis.value(units='M')
|
||||
if vis_m is None:
|
||||
return None
|
||||
|
||||
|
@@ -765,6 +765,9 @@ mbddns==0.1.2
|
||||
# homeassistant.components.message_bird
|
||||
messagebird==1.2.0
|
||||
|
||||
# homeassistant.components.nws
|
||||
metar==1.7.0
|
||||
|
||||
# homeassistant.components.meteoalarm
|
||||
meteoalertapi==0.1.5
|
||||
|
||||
|
@@ -40,6 +40,21 @@ OBS = [{
|
||||
'textDescription': 'Sunny'
|
||||
}]
|
||||
|
||||
METAR_MSG = ("PHNG 182257Z 06012KT 10SM FEW020 SCT026 SCT035 "
|
||||
"28/22 A3007 RMK AO2 SLP177 T02780217")
|
||||
|
||||
OBS_METAR = [{
|
||||
"rawMessage": METAR_MSG,
|
||||
"textDescription": "Partly Cloudy",
|
||||
"icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
|
||||
"temperature": {"value": None, "qualityControl": "qc:Z"},
|
||||
"windDirection": {"value": None, "qualityControl": "qc:Z"},
|
||||
"windSpeed": {"value": None, "qualityControl": "qc:Z"},
|
||||
"seaLevelPressure": {"value": None, "qualityControl": "qc:Z"},
|
||||
"visibility": {"value": None, "qualityControl": "qc:Z"},
|
||||
"relativeHumidity": {"value": None, "qualityControl": "qc:Z"},
|
||||
}]
|
||||
|
||||
FORE = [{
|
||||
'endTime': '2018-12-21T18:00:00-05:00',
|
||||
'windSpeed': '8 to 10 mph',
|
||||
@@ -306,3 +321,74 @@ class TestNwsMetric(unittest.TestCase):
|
||||
assert forecast[0].get(ATTR_FORECAST_WIND_BEARING) == 180
|
||||
assert forecast[0].get(ATTR_FORECAST_WIND_SPEED) == round(
|
||||
convert_distance(9, LENGTH_MILES, LENGTH_KILOMETERS))
|
||||
|
||||
|
||||
class MockNws_Metar():
|
||||
"""Mock Station from pynws."""
|
||||
|
||||
def __init__(self, websession, latlon, userid):
|
||||
"""Init mock nws."""
|
||||
pass
|
||||
|
||||
async def observations(self):
|
||||
"""Mock Observation."""
|
||||
return OBS_METAR
|
||||
|
||||
async def forecast(self):
|
||||
"""Mock Forecast."""
|
||||
return FORE
|
||||
|
||||
async def forecast_hourly(self):
|
||||
"""Mock Hourly Forecast."""
|
||||
return HOURLY_FORE
|
||||
|
||||
async def stations(self):
|
||||
"""Mock stations."""
|
||||
return [STN]
|
||||
|
||||
|
||||
class TestNWS_Metar(unittest.TestCase):
|
||||
"""Test the NWS weather component."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.units = IMPERIAL_SYSTEM
|
||||
self.lat = self.hass.config.latitude = 40.00
|
||||
self.lon = self.hass.config.longitude = -8.00
|
||||
|
||||
def tearDown(self):
|
||||
"""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
@MockDependency("pynws")
|
||||
@patch("pynws.Nws", new=MockNws_Metar)
|
||||
def test_metar(self, mock_pynws):
|
||||
"""Test for successfully setting up the NWS platform with name."""
|
||||
assert setup_component(self.hass, weather.DOMAIN, {
|
||||
'weather': {
|
||||
'name': 'HomeWeather',
|
||||
'platform': 'nws',
|
||||
'api_key': 'test_email',
|
||||
}
|
||||
})
|
||||
|
||||
from metar import Metar
|
||||
truth = Metar.Metar(METAR_MSG)
|
||||
state = self.hass.states.get('weather.homeweather')
|
||||
data = state.attributes
|
||||
|
||||
temp_f = convert_temperature(truth.temp.value(), TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT)
|
||||
assert data.get(ATTR_WEATHER_TEMPERATURE) == \
|
||||
display_temp(self.hass, temp_f, TEMP_FAHRENHEIT, PRECISION_WHOLE)
|
||||
assert data.get(ATTR_WEATHER_HUMIDITY) is None
|
||||
assert data.get(ATTR_WEATHER_PRESSURE) == round(
|
||||
convert_pressure(truth.press.value(units='HPA'), PRESSURE_HPA,
|
||||
PRESSURE_INHG),
|
||||
2)
|
||||
assert data.get(ATTR_WEATHER_WIND_SPEED) == round(
|
||||
truth.wind_speed.value(units='MPH'))
|
||||
assert data.get(ATTR_WEATHER_WIND_BEARING) == truth.wind_dir.value()
|
||||
assert data.get(ATTR_WEATHER_VISIBILITY) == round(
|
||||
truth.vis.value(units='MI'))
|
||||
|
Reference in New Issue
Block a user