mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Add new Meteoclimatic integration (#36906)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io> Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
@ -611,6 +611,9 @@ omit =
|
||||
homeassistant/components/meteo_france/sensor.py
|
||||
homeassistant/components/meteo_france/weather.py
|
||||
homeassistant/components/meteoalarm/*
|
||||
homeassistant/components/meteoclimatic/__init__.py
|
||||
homeassistant/components/meteoclimatic/const.py
|
||||
homeassistant/components/meteoclimatic/weather.py
|
||||
homeassistant/components/metoffice/sensor.py
|
||||
homeassistant/components/metoffice/weather.py
|
||||
homeassistant/components/microsoft/tts.py
|
||||
|
@ -290,6 +290,7 @@ homeassistant/components/met/* @danielhiversen @thimic
|
||||
homeassistant/components/met_eireann/* @DylanGore
|
||||
homeassistant/components/meteo_france/* @hacf-fr @oncleben31 @Quentame
|
||||
homeassistant/components/meteoalarm/* @rolfberkenbosch
|
||||
homeassistant/components/meteoclimatic/* @adrianmo
|
||||
homeassistant/components/metoffice/* @MrHarcombe
|
||||
homeassistant/components/miflora/* @danielhiversen @basnijholt
|
||||
homeassistant/components/mikrotik/* @engrbm87
|
||||
|
52
homeassistant/components/meteoclimatic/__init__.py
Normal file
52
homeassistant/components/meteoclimatic/__init__.py
Normal file
@ -0,0 +1,52 @@
|
||||
"""Support for Meteoclimatic weather data."""
|
||||
import logging
|
||||
|
||||
from meteoclimatic import MeteoclimaticClient
|
||||
from meteoclimatic.exceptions import MeteoclimaticError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import CONF_STATION_CODE, DOMAIN, PLATFORMS, SCAN_INTERVAL
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
|
||||
"""Set up a Meteoclimatic entry."""
|
||||
station_code = entry.data[CONF_STATION_CODE]
|
||||
meteoclimatic_client = MeteoclimaticClient()
|
||||
|
||||
async def async_update_data():
|
||||
"""Obtain the latest data from Meteoclimatic."""
|
||||
try:
|
||||
data = await hass.async_add_executor_job(
|
||||
meteoclimatic_client.weather_at_station, station_code
|
||||
)
|
||||
return data.__dict__
|
||||
except MeteoclimaticError as err:
|
||||
raise UpdateFailed(f"Error while retrieving data: {err}") from err
|
||||
|
||||
coordinator = DataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
name=f"Meteoclimatic Coordinator for {station_code}",
|
||||
update_method=async_update_data,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][entry.entry_id] = coordinator
|
||||
|
||||
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
return unload_ok
|
64
homeassistant/components/meteoclimatic/config_flow.py
Normal file
64
homeassistant/components/meteoclimatic/config_flow.py
Normal file
@ -0,0 +1,64 @@
|
||||
"""Config flow to configure the Meteoclimatic integration."""
|
||||
import logging
|
||||
|
||||
from meteoclimatic import MeteoclimaticClient
|
||||
from meteoclimatic.exceptions import MeteoclimaticError, StationNotFound
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
||||
from .const import CONF_STATION_CODE, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MeteoclimaticFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a Meteoclimatic config flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def _show_setup_form(self, user_input=None, errors=None):
|
||||
"""Show the setup form to the user."""
|
||||
if user_input is None:
|
||||
user_input = {}
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_STATION_CODE, default=user_input.get(CONF_STATION_CODE, "")
|
||||
): str
|
||||
}
|
||||
),
|
||||
errors=errors or {},
|
||||
)
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initiated by the user."""
|
||||
errors = {}
|
||||
|
||||
if user_input is None:
|
||||
return self._show_setup_form(user_input, errors)
|
||||
|
||||
station_code = user_input[CONF_STATION_CODE]
|
||||
client = MeteoclimaticClient()
|
||||
|
||||
try:
|
||||
weather = await self.hass.async_add_executor_job(
|
||||
client.weather_at_station, station_code
|
||||
)
|
||||
except StationNotFound as exp:
|
||||
_LOGGER.error("Station not found: %s", exp)
|
||||
errors["base"] = "not_found"
|
||||
return self._show_setup_form(user_input, errors)
|
||||
except MeteoclimaticError as exp:
|
||||
_LOGGER.error("Error when obtaining Meteoclimatic weather: %s", exp)
|
||||
return self.async_abort(reason="unknown")
|
||||
|
||||
# Check if already configured
|
||||
await self.async_set_unique_id(station_code, raise_on_progress=False)
|
||||
|
||||
return self.async_create_entry(
|
||||
title=weather.station.name, data={CONF_STATION_CODE: station_code}
|
||||
)
|
134
homeassistant/components/meteoclimatic/const.py
Normal file
134
homeassistant/components/meteoclimatic/const.py
Normal file
@ -0,0 +1,134 @@
|
||||
"""Meteoclimatic component constants."""
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from meteoclimatic import Condition
|
||||
|
||||
from homeassistant.components.weather import (
|
||||
ATTR_CONDITION_CLEAR_NIGHT,
|
||||
ATTR_CONDITION_CLOUDY,
|
||||
ATTR_CONDITION_EXCEPTIONAL,
|
||||
ATTR_CONDITION_FOG,
|
||||
ATTR_CONDITION_HAIL,
|
||||
ATTR_CONDITION_LIGHTNING,
|
||||
ATTR_CONDITION_LIGHTNING_RAINY,
|
||||
ATTR_CONDITION_PARTLYCLOUDY,
|
||||
ATTR_CONDITION_POURING,
|
||||
ATTR_CONDITION_RAINY,
|
||||
ATTR_CONDITION_SNOWY,
|
||||
ATTR_CONDITION_SNOWY_RAINY,
|
||||
ATTR_CONDITION_SUNNY,
|
||||
ATTR_CONDITION_WINDY,
|
||||
ATTR_CONDITION_WINDY_VARIANT,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
DEGREE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
LENGTH_MILLIMETERS,
|
||||
PERCENTAGE,
|
||||
PRESSURE_HPA,
|
||||
SPEED_KILOMETERS_PER_HOUR,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
|
||||
DOMAIN = "meteoclimatic"
|
||||
PLATFORMS = ["weather"]
|
||||
ATTRIBUTION = "Data provided by Meteoclimatic"
|
||||
|
||||
SCAN_INTERVAL = timedelta(minutes=10)
|
||||
|
||||
CONF_STATION_CODE = "station_code"
|
||||
|
||||
DEFAULT_WEATHER_CARD = True
|
||||
|
||||
SENSOR_TYPE_NAME = "name"
|
||||
SENSOR_TYPE_UNIT = "unit"
|
||||
SENSOR_TYPE_ICON = "icon"
|
||||
SENSOR_TYPE_CLASS = "device_class"
|
||||
SENSOR_TYPES = {
|
||||
"temp_current": {
|
||||
SENSOR_TYPE_NAME: "Temperature",
|
||||
SENSOR_TYPE_UNIT: TEMP_CELSIUS,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
},
|
||||
"temp_max": {
|
||||
SENSOR_TYPE_NAME: "Max Temp.",
|
||||
SENSOR_TYPE_UNIT: TEMP_CELSIUS,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
},
|
||||
"temp_min": {
|
||||
SENSOR_TYPE_NAME: "Min Temp.",
|
||||
SENSOR_TYPE_UNIT: TEMP_CELSIUS,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
},
|
||||
"humidity_current": {
|
||||
SENSOR_TYPE_NAME: "Humidity",
|
||||
SENSOR_TYPE_UNIT: PERCENTAGE,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_HUMIDITY,
|
||||
},
|
||||
"humidity_max": {
|
||||
SENSOR_TYPE_NAME: "Max Humidity",
|
||||
SENSOR_TYPE_UNIT: PERCENTAGE,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_HUMIDITY,
|
||||
},
|
||||
"humidity_min": {
|
||||
SENSOR_TYPE_NAME: "Min Humidity",
|
||||
SENSOR_TYPE_UNIT: PERCENTAGE,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_HUMIDITY,
|
||||
},
|
||||
"pressure_current": {
|
||||
SENSOR_TYPE_NAME: "Pressure",
|
||||
SENSOR_TYPE_UNIT: PRESSURE_HPA,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_PRESSURE,
|
||||
},
|
||||
"pressure_max": {
|
||||
SENSOR_TYPE_NAME: "Max Pressure",
|
||||
SENSOR_TYPE_UNIT: PRESSURE_HPA,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_PRESSURE,
|
||||
},
|
||||
"pressure_min": {
|
||||
SENSOR_TYPE_NAME: "Min Pressure",
|
||||
SENSOR_TYPE_UNIT: PRESSURE_HPA,
|
||||
SENSOR_TYPE_CLASS: DEVICE_CLASS_PRESSURE,
|
||||
},
|
||||
"wind_current": {
|
||||
SENSOR_TYPE_NAME: "Wind Speed",
|
||||
SENSOR_TYPE_UNIT: SPEED_KILOMETERS_PER_HOUR,
|
||||
SENSOR_TYPE_ICON: "mdi:weather-windy",
|
||||
},
|
||||
"wind_max": {
|
||||
SENSOR_TYPE_NAME: "Max Wind Speed",
|
||||
SENSOR_TYPE_UNIT: SPEED_KILOMETERS_PER_HOUR,
|
||||
SENSOR_TYPE_ICON: "mdi:weather-windy",
|
||||
},
|
||||
"wind_bearing": {
|
||||
SENSOR_TYPE_NAME: "Wind Bearing",
|
||||
SENSOR_TYPE_UNIT: DEGREE,
|
||||
SENSOR_TYPE_ICON: "mdi:weather-windy",
|
||||
},
|
||||
"rain": {
|
||||
SENSOR_TYPE_NAME: "Rain",
|
||||
SENSOR_TYPE_UNIT: LENGTH_MILLIMETERS,
|
||||
SENSOR_TYPE_ICON: "mdi:weather-rainy",
|
||||
},
|
||||
}
|
||||
|
||||
CONDITION_CLASSES = {
|
||||
ATTR_CONDITION_CLEAR_NIGHT: [Condition.moon, Condition.hazemoon],
|
||||
ATTR_CONDITION_CLOUDY: [Condition.mooncloud],
|
||||
ATTR_CONDITION_EXCEPTIONAL: [],
|
||||
ATTR_CONDITION_FOG: [Condition.fog, Condition.mist],
|
||||
ATTR_CONDITION_HAIL: [],
|
||||
ATTR_CONDITION_LIGHTNING: [Condition.storm],
|
||||
ATTR_CONDITION_LIGHTNING_RAINY: [],
|
||||
ATTR_CONDITION_PARTLYCLOUDY: [Condition.suncloud, Condition.hazesun],
|
||||
ATTR_CONDITION_POURING: [],
|
||||
ATTR_CONDITION_RAINY: [Condition.rain],
|
||||
ATTR_CONDITION_SNOWY: [],
|
||||
ATTR_CONDITION_SNOWY_RAINY: [],
|
||||
ATTR_CONDITION_SUNNY: [Condition.sun],
|
||||
ATTR_CONDITION_WINDY: [],
|
||||
ATTR_CONDITION_WINDY_VARIANT: [],
|
||||
}
|
13
homeassistant/components/meteoclimatic/manifest.json
Normal file
13
homeassistant/components/meteoclimatic/manifest.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"domain": "meteoclimatic",
|
||||
"name": "Meteoclimatic",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/meteoclimatic",
|
||||
"requirements": [
|
||||
"pymeteoclimatic==0.0.6"
|
||||
],
|
||||
"codeowners": [
|
||||
"@adrianmo"
|
||||
],
|
||||
"iot_class": "cloud_polling"
|
||||
}
|
20
homeassistant/components/meteoclimatic/strings.json
Normal file
20
homeassistant/components/meteoclimatic/strings.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Meteoclimatic",
|
||||
"description": "Enter the Meteoclimatic station code (e.g., ESCAT4300000043206B)",
|
||||
"data": {
|
||||
"code": "Station code"
|
||||
}
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"error": {
|
||||
"not_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
||||
}
|
||||
}
|
||||
}
|
20
homeassistant/components/meteoclimatic/translations/en.json
Normal file
20
homeassistant/components/meteoclimatic/translations/en.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Station already configured",
|
||||
"unknown": "Unknown error: please try again later"
|
||||
},
|
||||
"error": {
|
||||
"not_found": "The station code did not return any data. Check that the code belongs to a station and it has the right format (e.g., ESCAT4300000043206B)"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"code": "Station code"
|
||||
},
|
||||
"description": "Enter the Meteoclimatic station code (e.g., ESCAT4300000043206B)",
|
||||
"title": "Meteoclimatic"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
homeassistant/components/meteoclimatic/weather.py
Normal file
93
homeassistant/components/meteoclimatic/weather.py
Normal file
@ -0,0 +1,93 @@
|
||||
"""Support for Meteoclimatic weather service."""
|
||||
from meteoclimatic import Condition
|
||||
|
||||
from homeassistant.components.weather import WeatherEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
)
|
||||
|
||||
from .const import ATTRIBUTION, CONDITION_CLASSES, DOMAIN
|
||||
|
||||
|
||||
def format_condition(condition):
|
||||
"""Return condition from dict CONDITION_CLASSES."""
|
||||
for key, value in CONDITION_CLASSES.items():
|
||||
if condition in value:
|
||||
return key
|
||||
if isinstance(condition, Condition):
|
||||
return condition.value
|
||||
return condition
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Set up the Meteoclimatic weather platform."""
|
||||
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
async_add_entities([MeteoclimaticWeather(coordinator)], False)
|
||||
|
||||
|
||||
class MeteoclimaticWeather(CoordinatorEntity, WeatherEntity):
|
||||
"""Representation of a weather condition."""
|
||||
|
||||
def __init__(self, coordinator: DataUpdateCoordinator) -> None:
|
||||
"""Initialise the weather platform."""
|
||||
super().__init__(coordinator)
|
||||
self._unique_id = self.coordinator.data["station"].code
|
||||
self._name = self.coordinator.data["station"].name
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the unique id of the sensor."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def condition(self):
|
||||
"""Return the current condition."""
|
||||
return format_condition(self.coordinator.data["weather"].condition)
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""Return the temperature."""
|
||||
return self.coordinator.data["weather"].temp_current
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS
|
||||
|
||||
@property
|
||||
def humidity(self):
|
||||
"""Return the humidity."""
|
||||
return self.coordinator.data["weather"].humidity_current
|
||||
|
||||
@property
|
||||
def pressure(self):
|
||||
"""Return the pressure."""
|
||||
return self.coordinator.data["weather"].pressure_current
|
||||
|
||||
@property
|
||||
def wind_speed(self):
|
||||
"""Return the wind speed."""
|
||||
return self.coordinator.data["weather"].wind_current
|
||||
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the wind bearing."""
|
||||
return self.coordinator.data["weather"].wind_bearing
|
||||
|
||||
@property
|
||||
def attribution(self):
|
||||
"""Return the attribution."""
|
||||
return ATTRIBUTION
|
@ -150,6 +150,7 @@ FLOWS = [
|
||||
"met",
|
||||
"met_eireann",
|
||||
"meteo_france",
|
||||
"meteoclimatic",
|
||||
"metoffice",
|
||||
"mikrotik",
|
||||
"mill",
|
||||
|
@ -1559,6 +1559,9 @@ pymediaroom==0.6.4.1
|
||||
# homeassistant.components.melcloud
|
||||
pymelcloud==2.5.2
|
||||
|
||||
# homeassistant.components.meteoclimatic
|
||||
pymeteoclimatic==0.0.6
|
||||
|
||||
# homeassistant.components.somfy
|
||||
pymfy==0.9.3
|
||||
|
||||
|
@ -870,6 +870,9 @@ pymazda==0.1.5
|
||||
# homeassistant.components.melcloud
|
||||
pymelcloud==2.5.2
|
||||
|
||||
# homeassistant.components.meteoclimatic
|
||||
pymeteoclimatic==0.0.6
|
||||
|
||||
# homeassistant.components.somfy
|
||||
pymfy==0.9.3
|
||||
|
||||
|
1
tests/components/meteoclimatic/__init__.py
Normal file
1
tests/components/meteoclimatic/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the Meteoclimatic component."""
|
13
tests/components/meteoclimatic/conftest.py
Normal file
13
tests/components/meteoclimatic/conftest.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""Meteoclimatic generic test utils."""
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_requests():
|
||||
"""Stub out services that makes requests."""
|
||||
patch_client = patch("homeassistant.components.meteoclimatic.MeteoclimaticClient")
|
||||
|
||||
with patch_client:
|
||||
yield
|
88
tests/components/meteoclimatic/test_config_flow.py
Normal file
88
tests/components/meteoclimatic/test_config_flow.py
Normal file
@ -0,0 +1,88 @@
|
||||
"""Tests for the Meteoclimatic config flow."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from meteoclimatic.exceptions import MeteoclimaticError, StationNotFound
|
||||
import pytest
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.meteoclimatic.const import CONF_STATION_CODE, DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
|
||||
TEST_STATION_CODE = "ESCAT4300000043206B"
|
||||
TEST_STATION_NAME = "Reus (Tarragona)"
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def mock_controller_client():
|
||||
"""Mock a successful client."""
|
||||
with patch(
|
||||
"homeassistant.components.meteoclimatic.config_flow.MeteoclimaticClient",
|
||||
update=False,
|
||||
) as service_mock:
|
||||
service_mock.return_value.get_data.return_value = {
|
||||
"station_code": TEST_STATION_CODE
|
||||
}
|
||||
weather = service_mock.return_value.weather_at_station.return_value
|
||||
weather.station.name = TEST_STATION_NAME
|
||||
yield service_mock
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_setup():
|
||||
"""Prevent setup."""
|
||||
with patch(
|
||||
"homeassistant.components.meteoclimatic.async_setup_entry",
|
||||
return_value=True,
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
async def test_user(hass, client):
|
||||
"""Test user config."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
# test with all provided
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
data={CONF_STATION_CODE: TEST_STATION_CODE},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["result"].unique_id == TEST_STATION_CODE
|
||||
assert result["title"] == TEST_STATION_NAME
|
||||
assert result["data"][CONF_STATION_CODE] == TEST_STATION_CODE
|
||||
|
||||
|
||||
async def test_not_found(hass):
|
||||
"""Test when we have the station code is not found."""
|
||||
with patch(
|
||||
"homeassistant.components.meteoclimatic.config_flow.MeteoclimaticClient.weather_at_station",
|
||||
side_effect=StationNotFound(TEST_STATION_CODE),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
data={CONF_STATION_CODE: TEST_STATION_CODE},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"]["base"] == "not_found"
|
||||
|
||||
|
||||
async def test_unknown_error(hass):
|
||||
"""Test when we have an unknown error fetching station data."""
|
||||
with patch(
|
||||
"homeassistant.components.meteoclimatic.config_flow.MeteoclimaticClient.weather_at_station",
|
||||
side_effect=MeteoclimaticError,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
data={CONF_STATION_CODE: TEST_STATION_CODE},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "unknown"
|
Reference in New Issue
Block a user