def _init_data(self): """Initialize a data object.""" conf = self._config if self.track_home: latitude = self.hass.config.latitude longitude = self.hass.config.longitude elevation = self.hass.config.elevation else: latitude = conf[CONF_LATITUDE] longitude = conf[CONF_LONGITUDE] elevation = conf[CONF_ELEVATION] if not self._is_metric: elevation = int( round(convert_distance(elevation, LENGTH_FEET, LENGTH_METERS))) coordinates = { "lat": str(latitude), "lon": str(longitude), "msl": str(elevation), } self._weather_data = metno.MetWeatherData( coordinates, async_get_clientsession(self.hass), URL)
"windDirection": 180, "visibility": 10000, "textDescription": "A long description", "station": "ABC", "timestamp": "2019-08-12T23:53:00+00:00", "iconTime": "day", "iconWeather": (("Fair/clear", None), ), } EXPECTED_OBSERVATION_IMPERIAL = { ATTR_WEATHER_TEMPERATURE: round(convert_temperature(10, TEMP_CELSIUS, TEMP_FAHRENHEIT)), ATTR_WEATHER_WIND_BEARING: 180, ATTR_WEATHER_WIND_SPEED: round(convert_distance(10, LENGTH_METERS, LENGTH_MILES) * 3600), ATTR_WEATHER_PRESSURE: round(convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2), ATTR_WEATHER_VISIBILITY: round(convert_distance(10000, LENGTH_METERS, LENGTH_MILES)), ATTR_WEATHER_HUMIDITY: 10, } EXPECTED_OBSERVATION_METRIC = { ATTR_WEATHER_TEMPERATURE: 10, ATTR_WEATHER_WIND_BEARING: 180, ATTR_WEATHER_WIND_SPEED: round(convert_distance(10, LENGTH_METERS, LENGTH_KILOMETERS) * 3600),
) 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
"heatIndex": str(round(convert_temperature(15, TEMP_CELSIUS, TEMP_FAHRENHEIT))), "relativeHumidity": "10", "windSpeed": str( round(convert_speed(10, SPEED_KILOMETERS_PER_HOUR, SPEED_MILES_PER_HOUR)) ), "windGust": str( round(convert_speed(20, SPEED_KILOMETERS_PER_HOUR, SPEED_MILES_PER_HOUR)) ), "windDirection": "180", "barometricPressure": str( round(convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2) ), "seaLevelPressure": str( round(convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2) ), "visibility": str(round(convert_distance(10000, LENGTH_METERS, LENGTH_MILES))), } WEATHER_EXPECTED_OBSERVATION_IMPERIAL = { ATTR_WEATHER_TEMPERATURE: round( convert_temperature(10, TEMP_CELSIUS, TEMP_FAHRENHEIT) ), ATTR_WEATHER_WIND_BEARING: 180, ATTR_WEATHER_WIND_SPEED: round( convert_speed(10, SPEED_KILOMETERS_PER_HOUR, SPEED_MILES_PER_HOUR), 2 ), ATTR_WEATHER_PRESSURE: round( convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2 ), ATTR_WEATHER_VISIBILITY: round( convert_distance(10000, LENGTH_METERS, LENGTH_MILES), 2
"visibility": "10000", } SENSOR_EXPECTED_OBSERVATION_IMPERIAL = { "dewpoint": str(round(convert_temperature(5, TEMP_CELSIUS, TEMP_FAHRENHEIT))), "temperature": str(round(convert_temperature(10, TEMP_CELSIUS, TEMP_FAHRENHEIT))), "windChill": str(round(convert_temperature(5, TEMP_CELSIUS, TEMP_FAHRENHEIT))), "heatIndex": str(round(convert_temperature(15, TEMP_CELSIUS, TEMP_FAHRENHEIT))), "relativeHumidity": "10", "windSpeed": str(round(convert_distance(10, LENGTH_KILOMETERS, LENGTH_MILES))), "windGust": str(round(convert_distance(20, LENGTH_KILOMETERS, LENGTH_MILES))), "windDirection": "180", "barometricPressure": str(round(convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2)), "seaLevelPressure": str(round(convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2)), "visibility": str(round(convert_distance(10000, LENGTH_METERS, LENGTH_MILES))), } WEATHER_EXPECTED_OBSERVATION_IMPERIAL = { ATTR_WEATHER_TEMPERATURE: round(convert_temperature(10, TEMP_CELSIUS, TEMP_FAHRENHEIT)),
async def test_backwards_compatibility_convert_values( hass: HomeAssistant, enable_custom_integrations) -> None: """Test backward compatibility for converting values.""" wind_speed_value = 5 wind_speed_unit = SPEED_METERS_PER_SECOND pressure_value = 110000 pressure_unit = PRESSURE_PA temperature_value = 20 temperature_unit = TEMP_CELSIUS visibility_value = 11 visibility_unit = LENGTH_KILOMETERS precipitation_value = 1 precipitation_unit = LENGTH_MILLIMETERS hass.config.units = IMPERIAL_SYSTEM platform: WeatherPlatform = getattr(hass.components, "test.weather") platform.init(empty=True) platform.ENTITIES.append( platform.MockWeatherMockForecastCompat( name="Test", condition=ATTR_CONDITION_SUNNY, temperature=temperature_value, temperature_unit=temperature_unit, wind_speed=wind_speed_value, wind_speed_unit=wind_speed_unit, pressure=pressure_value, pressure_unit=pressure_unit, visibility=visibility_value, visibility_unit=visibility_unit, precipitation=precipitation_value, precipitation_unit=precipitation_unit, unique_id="very_unique", )) entity0 = platform.ENTITIES[0] assert await async_setup_component(hass, "weather", {"weather": { "platform": "test" }}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) expected_wind_speed = round( convert_speed(wind_speed_value, wind_speed_unit, SPEED_MILES_PER_HOUR), ROUNDING_PRECISION, ) expected_temperature = convert_temperature(temperature_value, temperature_unit, TEMP_FAHRENHEIT) expected_pressure = round( convert_pressure(pressure_value, pressure_unit, PRESSURE_INHG), ROUNDING_PRECISION, ) expected_visibility = round( convert_distance(visibility_value, visibility_unit, LENGTH_MILES), ROUNDING_PRECISION, ) expected_precipitation = round( convert_distance(precipitation_value, precipitation_unit, LENGTH_INCHES), ROUNDING_PRECISION, ) assert state.attributes == { ATTR_FORECAST: [{ ATTR_FORECAST_PRECIPITATION: approx(expected_precipitation, rel=0.1), ATTR_FORECAST_PRESSURE: approx(expected_pressure, rel=0.1), ATTR_FORECAST_TEMP: approx(expected_temperature, rel=0.1), ATTR_FORECAST_TEMP_LOW: approx(expected_temperature, rel=0.1), ATTR_FORECAST_WIND_BEARING: None, ATTR_FORECAST_WIND_SPEED: approx(expected_wind_speed, rel=0.1), }], ATTR_FRIENDLY_NAME: "Test", ATTR_WEATHER_PRECIPITATION_UNIT: LENGTH_INCHES, ATTR_WEATHER_PRESSURE: approx(expected_pressure, rel=0.1), ATTR_WEATHER_PRESSURE_UNIT: PRESSURE_INHG, ATTR_WEATHER_TEMPERATURE: approx(expected_temperature, rel=0.1), ATTR_WEATHER_TEMPERATURE_UNIT: TEMP_FAHRENHEIT, ATTR_WEATHER_VISIBILITY: approx(expected_visibility, rel=0.1), ATTR_WEATHER_VISIBILITY_UNIT: LENGTH_MILES, ATTR_WEATHER_WIND_SPEED: approx(expected_wind_speed, rel=0.1), ATTR_WEATHER_WIND_SPEED_UNIT: SPEED_MILES_PER_HOUR, }
async def test_custom_units(hass: HomeAssistant, enable_custom_integrations) -> None: """Test custom unit.""" wind_speed_value = 5 wind_speed_unit = SPEED_METERS_PER_SECOND pressure_value = 110 pressure_unit = PRESSURE_HPA temperature_value = 20 temperature_unit = TEMP_CELSIUS visibility_value = 11 visibility_unit = LENGTH_KILOMETERS precipitation_value = 1.1 precipitation_unit = LENGTH_MILLIMETERS set_options = { "wind_speed_unit": SPEED_MILES_PER_HOUR, "precipitation_unit": LENGTH_INCHES, "pressure_unit": PRESSURE_INHG, "temperature_unit": TEMP_FAHRENHEIT, "visibility_unit": LENGTH_MILES, } entity_registry = er.async_get(hass) entry = entity_registry.async_get_or_create("weather", "test", "very_unique") entity_registry.async_update_entity_options(entry.entity_id, "weather", set_options) await hass.async_block_till_done() platform: WeatherPlatform = getattr(hass.components, "test.weather") platform.init(empty=True) platform.ENTITIES.append( platform.MockWeatherMockForecast( name="Test", condition=ATTR_CONDITION_SUNNY, native_temperature=temperature_value, native_temperature_unit=temperature_unit, native_wind_speed=wind_speed_value, native_wind_speed_unit=wind_speed_unit, native_pressure=pressure_value, native_pressure_unit=pressure_unit, native_visibility=visibility_value, native_visibility_unit=visibility_unit, native_precipitation=precipitation_value, native_precipitation_unit=precipitation_unit, unique_id="very_unique", )) entity0 = platform.ENTITIES[0] assert await async_setup_component(hass, "weather", {"weather": { "platform": "test" }}) await hass.async_block_till_done() state = hass.states.get(entity0.entity_id) forecast = state.attributes[ATTR_FORECAST][0] expected_wind_speed = round( convert_speed(wind_speed_value, wind_speed_unit, SPEED_MILES_PER_HOUR), ROUNDING_PRECISION, ) expected_temperature = convert_temperature(temperature_value, temperature_unit, TEMP_FAHRENHEIT) expected_pressure = round( convert_pressure(pressure_value, pressure_unit, PRESSURE_INHG), ROUNDING_PRECISION, ) expected_visibility = round( convert_distance(visibility_value, visibility_unit, LENGTH_MILES), ROUNDING_PRECISION, ) expected_precipitation = round( convert_distance(precipitation_value, precipitation_unit, LENGTH_INCHES), ROUNDING_PRECISION, ) assert float(state.attributes[ATTR_WEATHER_WIND_SPEED]) == approx( expected_wind_speed) assert float(state.attributes[ATTR_WEATHER_TEMPERATURE]) == approx( expected_temperature, rel=0.1) assert float( state.attributes[ATTR_WEATHER_PRESSURE]) == approx(expected_pressure) assert float(state.attributes[ATTR_WEATHER_VISIBILITY]) == approx( expected_visibility) assert float(forecast[ATTR_FORECAST_PRECIPITATION]) == approx( expected_precipitation, rel=1e-2) assert (state.attributes[ATTR_WEATHER_PRECIPITATION_UNIT] == set_options["precipitation_unit"]) assert state.attributes[ATTR_WEATHER_PRESSURE_UNIT] == set_options[ "pressure_unit"] assert (state.attributes[ATTR_WEATHER_TEMPERATURE_UNIT] == set_options["temperature_unit"]) assert (state.attributes[ATTR_WEATHER_VISIBILITY_UNIT] == set_options["visibility_unit"]) assert (state.attributes[ATTR_WEATHER_WIND_SPEED_UNIT] == set_options["wind_speed_unit"])
async def async_update(self, *_): """Get the latest data""" def try_again(err: str): """Retry""" _LOGGER.error("Will try again shortly: %s", err) async_call_later(self.hass, 2 * 60, self.async_update) try: websession = async_get_clientsession(self.hass) with async_timeout.timeout(10, loop=self.hass.loop): resp = await websession.get(self._url) if resp.status != 200: try_again('{} returned {}'.format(resp.url, resp.status)) return text = await resp.text() except (asyncio.TimeoutError, aiohttp.ClientError) as err: try_again(err) return try: self.data = text.split(' ') if len(self.data) < 115: raise ValueError('Could not parse the file') except (ExpatError, IndexError) as err: try_again(err) return if not self.data: return # Update all devices tasks = [] for dev in self.devices: new_state = None if dev.type == 'symbol': new_state = int(self.data[48]) elif dev.type == 'daily_rain': rain = float(self.data[7]) if not self.hass.config.units.is_metric: rain = rain * 0.0393700787 new_state = round(rain, 2) elif dev.type == 'rain_rate': rate = float(self.data[10]) if not self.hass.config.units.is_metric: rate = rate * 0.0393700787 new_state = round(rate, 2) elif dev.type == 'temp': temperature = float(self.data[4]) if not self.hass.config.units.is_metric: temperature = convert_temperature(temperature, TEMP_CELSIUS, TEMP_FAHRENHEIT) new_state = round(temperature, 2) elif dev.type == 'wind_speed': speed = float(self.data[1]) if self.hass.config.units.is_metric: new_state = speed * 1.85166 else: new_state = speed * 1.1507794 new_state = round(speed, 2) elif dev.type == 'wind_gust': gust = float(self.data[2]) if self.hass.config.units.is_metric: new_state = gust * 1.85166 else: new_state = gust * 1.1507794 new_state = round(gust, 2) elif dev.type == 'pressure': pressure = float(self.data[6]) if not self.hass.config.units.is_metric: pressure = round( convert_pressure(pressure, PRESSURE_HPA, PRESSURE_INHG), 2) new_state = round(pressure, 2) elif dev.type == 'wind_degrees': new_state = float(self.data[3]) elif dev.type == 'wind_dir': direction = float(self.data[3]) val = int((direction / 22.5) + .5) arr = [ "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" ] new_state = arr[(val % 16)] elif dev.type == 'humidity': new_state = float(self.data[5]) elif dev.type == 'cloud_height': height = float(self.data[73]) if not self.hass.config.units.is_metric: height = convert_distance(height, LENGTH_METERS, LENGTH_FEET) new_state = round(height, 2) elif dev.type == 'dewpoint': temperature = float(self.data[72]) if not self.hass.config.units.is_metric: temperature = convert_temperature(temperature, TEMP_CELSIUS, TEMP_FAHRENHEIT) new_state = round(temperature, 2) elif dev.type == 'heat_index': temperature = float(self.data[112]) if not self.hass.config.units.is_metric: temperature = convert_temperature(temperature, TEMP_CELSIUS, TEMP_FAHRENHEIT) new_state = round(temperature, 2) elif dev.type == 'humidex': temperature = float(self.data[44]) if not self.hass.config.units.is_metric: temperature = convert_temperature(temperature, TEMP_CELSIUS, TEMP_FAHRENHEIT) new_state = round(temperature, 2) elif dev.type == 'forecast': val = int(self.data[15]) arr = [ "sunny", "clearnight", "cloudy", "cloudy2", "night cloudy", "dry", "fog", "haze", "heavyrain", "mainlyfine", "mist", "night fog", "night heavyrain", "night overcast", "night rain", "night showers", "night snow", "night", "thunder", "overcast", "partlycloudy", "rain", "rain2", "showers2", "sleet", "sleetshowers", "snow", "snowmelt", "snowshowers2", "sunny", "thundershowers", "thundershowers2", "thunderstorms", "tornado", "windy", "stopped", "rainning", "wind + rain" ] new_state = arr[(val)] if val < len(arr) else "unknown" _LOGGER.debug("%s %s", dev.type, new_state) # pylint: disable=protected-access if new_state != dev._state: dev._state = new_state tasks.append(dev.async_update_ha_state()) if tasks: await asyncio.wait(tasks, loop=self.hass.loop) async_call_later(self.hass, self._interval * 60, self.async_update)
"windDirection": 180, "visibility": 10000, "textDescription": "A long description", "station": "ABC", "timestamp": "2019-08-12T23:53:00+00:00", "iconTime": "day", "iconWeather": (("Fair/clear", None),), } EXPECTED_OBSERVATION_IMPERIAL = { ATTR_WEATHER_TEMPERATURE: round( convert_temperature(10, TEMP_CELSIUS, TEMP_FAHRENHEIT) ), ATTR_WEATHER_WIND_BEARING: 180, ATTR_WEATHER_WIND_SPEED: round( convert_distance(10, LENGTH_KILOMETERS, LENGTH_MILES) ), ATTR_WEATHER_PRESSURE: round( convert_pressure(100000, PRESSURE_PA, PRESSURE_INHG), 2 ), ATTR_WEATHER_VISIBILITY: round( convert_distance(10000, LENGTH_METERS, LENGTH_MILES) ), ATTR_WEATHER_HUMIDITY: 10, } EXPECTED_OBSERVATION_METRIC = { ATTR_WEATHER_TEMPERATURE: 10, ATTR_WEATHER_WIND_BEARING: 180, ATTR_WEATHER_WIND_SPEED: 10, ATTR_WEATHER_PRESSURE: round(convert_pressure(100000, PRESSURE_PA, PRESSURE_HPA)),