parent
f382be4c15
commit
a89c8eeabe
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"name_exists": "Name already exists"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"elevation": "Elevation",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"name": "Name"
|
||||
},
|
||||
"description": "Meteorologisk institutt",
|
||||
"title": "Location"
|
||||
}
|
||||
},
|
||||
"title": "Met.no"
|
||||
}
|
||||
}
|
|
@ -1 +1,23 @@
|
|||
"""The met component."""
|
||||
from homeassistant.core import Config, HomeAssistant
|
||||
from .config_flow import MetFlowHandler # noqa
|
||||
from .const import DOMAIN # noqa
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: Config) -> bool:
|
||||
"""Set up configured Met."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry):
|
||||
"""Set up Met as config entry."""
|
||||
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
|
||||
config_entry, 'weather'))
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass, config_entry):
|
||||
"""Unload a config entry."""
|
||||
await hass.config_entries.async_forward_entry_unload(
|
||||
config_entry, 'weather')
|
||||
return True
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
"""Config flow to configure Met component."""
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.const import (
|
||||
CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME)
|
||||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import DOMAIN, HOME_LOCATION_NAME
|
||||
|
||||
|
||||
@callback
|
||||
def configured_instances(hass):
|
||||
"""Return a set of configured SimpliSafe instances."""
|
||||
return set(
|
||||
entry.data[CONF_NAME]
|
||||
for entry in hass.config_entries.async_entries(DOMAIN))
|
||||
|
||||
|
||||
@config_entries.HANDLERS.register(DOMAIN)
|
||||
class MetFlowHandler(data_entry_flow.FlowHandler):
|
||||
"""Config flow for Met component."""
|
||||
|
||||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
|
||||
|
||||
def __init__(self):
|
||||
"""Init MetFlowHandler."""
|
||||
self._errors = {}
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
self._errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
if user_input[CONF_NAME] not in configured_instances(self.hass):
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_NAME],
|
||||
data=user_input,
|
||||
)
|
||||
|
||||
self._errors[CONF_NAME] = 'name_exists'
|
||||
|
||||
return await self._show_config_form(
|
||||
name=HOME_LOCATION_NAME,
|
||||
latitude=self.hass.config.latitude,
|
||||
longitude=self.hass.config.longitude,
|
||||
elevation=self.hass.config.elevation)
|
||||
|
||||
async def _show_config_form(self, name=None, latitude=None,
|
||||
longitude=None, elevation=None):
|
||||
"""Show the configuration form to edit location data."""
|
||||
return self.async_show_form(
|
||||
step_id='user',
|
||||
data_schema=vol.Schema({
|
||||
vol.Required(CONF_NAME, default=name): str,
|
||||
vol.Required(CONF_LATITUDE, default=latitude): cv.latitude,
|
||||
vol.Required(CONF_LONGITUDE, default=longitude): cv.longitude,
|
||||
vol.Required(CONF_ELEVATION, default=elevation): int
|
||||
}),
|
||||
errors=self._errors,
|
||||
)
|
|
@ -0,0 +1,14 @@
|
|||
"""Constants for Met component."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
|
||||
|
||||
DOMAIN = 'met'
|
||||
|
||||
HOME_LOCATION_NAME = 'Home'
|
||||
|
||||
ENTITY_ID_SENSOR_FORMAT = WEATHER_DOMAIN + ".met_{}"
|
||||
ENTITY_ID_SENSOR_FORMAT_HOME = ENTITY_ID_SENSOR_FORMAT.format(
|
||||
HOME_LOCATION_NAME)
|
||||
|
||||
_LOGGER = logging.getLogger('.')
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"domain": "met",
|
||||
"name": "Met",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/components/met",
|
||||
"requirements": [
|
||||
"pyMetno==0.4.6"
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"config": {
|
||||
"title": "Met.no",
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Location",
|
||||
"description": "Meteorologisk institutt",
|
||||
"data": {
|
||||
"name": "Name",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"elevation": "Elevation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"name_exists": "Name already exists"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,23 +33,43 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the Met.no weather platform."""
|
||||
elevation = config.get(CONF_ELEVATION, hass.config.elevation or 0)
|
||||
_LOGGER.warning("Loading Met.no via platform config is deprecated")
|
||||
|
||||
name = config.get(CONF_NAME)
|
||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
name = config.get(CONF_NAME)
|
||||
elevation = config.get(CONF_ELEVATION, hass.config.elevation or 0)
|
||||
|
||||
if None in (latitude, longitude):
|
||||
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
|
||||
return
|
||||
|
||||
station = await async_get_station(
|
||||
hass, name, latitude, longitude, elevation)
|
||||
async_add_entities([station])
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Add a weather entity from a config_entry."""
|
||||
name = config_entry.data.get(CONF_NAME)
|
||||
latitude = config_entry.data[CONF_LATITUDE]
|
||||
longitude = config_entry.data[CONF_LONGITUDE]
|
||||
elevation = config_entry.data[CONF_ELEVATION]
|
||||
|
||||
station = await async_get_station(
|
||||
hass, name, latitude, longitude, elevation)
|
||||
async_add_entities([station])
|
||||
|
||||
|
||||
async def async_get_station(hass, name, latitude, longitude, elevation):
|
||||
"""Retrieve weather station, station name to be used as the entity name."""
|
||||
coordinates = {
|
||||
'lat': str(latitude),
|
||||
'lon': str(longitude),
|
||||
'msl': str(elevation),
|
||||
}
|
||||
|
||||
async_add_entities([MetWeather(
|
||||
name, coordinates, async_get_clientsession(hass))])
|
||||
return MetWeather(name, coordinates, async_get_clientsession(hass))
|
||||
|
||||
|
||||
class MetWeather(WeatherEntity):
|
||||
|
|
|
@ -32,6 +32,7 @@ FLOWS = [
|
|||
"logi_circle",
|
||||
"luftdaten",
|
||||
"mailgun",
|
||||
"met",
|
||||
"mobile_app",
|
||||
"mqtt",
|
||||
"nest",
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
"""Tests for Met.no config flow."""
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from tests.common import MockConfigEntry, mock_coro
|
||||
|
||||
from homeassistant.const import CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE
|
||||
from homeassistant.components.met import config_flow
|
||||
|
||||
|
||||
async def test_show_config_form():
|
||||
"""Test show configuration form."""
|
||||
hass = Mock()
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow._show_config_form()
|
||||
|
||||
assert result['type'] == 'form'
|
||||
assert result['step_id'] == 'user'
|
||||
|
||||
|
||||
async def test_show_config_form_default_values():
|
||||
"""Test show configuration form."""
|
||||
hass = Mock()
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow._show_config_form(
|
||||
name="test", latitude='0', longitude='0', elevation='0')
|
||||
|
||||
assert result['type'] == 'form'
|
||||
assert result['step_id'] == 'user'
|
||||
|
||||
|
||||
async def test_flow_with_home_location(hass):
|
||||
"""Test config flow .
|
||||
|
||||
Tests the flow when a default location is configured
|
||||
then it should return a form with default values
|
||||
"""
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
hass.config.location_name = 'Home'
|
||||
hass.config.latitude = 1
|
||||
hass.config.longitude = 1
|
||||
hass.config.elevation = 1
|
||||
|
||||
result = await flow.async_step_user()
|
||||
assert result['type'] == 'form'
|
||||
assert result['step_id'] == 'user'
|
||||
|
||||
|
||||
async def test_flow_show_form():
|
||||
"""Test show form scenarios first time.
|
||||
|
||||
Test when the form should show when no configurations exists
|
||||
"""
|
||||
hass = Mock()
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
with \
|
||||
patch.object(flow, '_show_config_form',
|
||||
return_value=mock_coro()) as config_form:
|
||||
await flow.async_step_user()
|
||||
assert len(config_form.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_flow_entry_created_from_user_input():
|
||||
"""Test that create data from user input.
|
||||
|
||||
Test when the form should show when no configurations exists
|
||||
"""
|
||||
hass = Mock()
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
test_data = {
|
||||
'name': 'home',
|
||||
CONF_LONGITUDE: '0',
|
||||
CONF_LATITUDE: '0',
|
||||
CONF_ELEVATION: '0'
|
||||
}
|
||||
|
||||
# Test that entry created when user_input name not exists
|
||||
with \
|
||||
patch.object(flow, '_show_config_form',
|
||||
return_value=mock_coro()) as config_form,\
|
||||
patch.object(flow.hass.config_entries, 'async_entries',
|
||||
return_value=mock_coro()) as config_entries:
|
||||
|
||||
result = await flow.async_step_user(user_input=test_data)
|
||||
|
||||
assert result['type'] == 'create_entry'
|
||||
assert result['data'] == test_data
|
||||
assert len(config_entries.mock_calls) == 1
|
||||
assert not config_form.mock_calls
|
||||
|
||||
|
||||
async def test_flow_entry_config_entry_already_exists():
|
||||
"""Test that create data from user input and config_entry already exists.
|
||||
|
||||
Test when the form should show when user puts existing name
|
||||
in the config gui. Then the form should show with error
|
||||
"""
|
||||
hass = Mock()
|
||||
|
||||
flow = config_flow.MetFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
first_entry = MockConfigEntry(domain='met')
|
||||
first_entry.data['name'] = 'home'
|
||||
first_entry.add_to_hass(hass)
|
||||
|
||||
test_data = {
|
||||
'name': 'home',
|
||||
CONF_LONGITUDE: '0',
|
||||
CONF_LATITUDE: '0',
|
||||
CONF_ELEVATION: '0'
|
||||
}
|
||||
|
||||
with \
|
||||
patch.object(flow, '_show_config_form',
|
||||
return_value=mock_coro()) as config_form,\
|
||||
patch.object(flow.hass.config_entries, 'async_entries',
|
||||
return_value=[first_entry]) as config_entries:
|
||||
|
||||
await flow.async_step_user(user_input=test_data)
|
||||
|
||||
assert len(config_form.mock_calls) == 1
|
||||
assert len(config_entries.mock_calls) == 1
|
||||
assert len(flow._errors) == 1
|
Loading…
Reference in New Issue