Add config entry for Met.no (#24608)

* Add config entry for Met.no

* Fixed tests
pull/24620/head
Aaron Bach 2019-06-18 17:44:41 -06:00 committed by GitHub
parent f382be4c15
commit a89c8eeabe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 298 additions and 4 deletions

View File

@ -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"
}
}

View File

@ -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

View File

@ -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,
)

View File

@ -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('.')

View File

@ -1,6 +1,7 @@
{
"domain": "met",
"name": "Met",
"config_flow": true,
"documentation": "https://www.home-assistant.io/components/met",
"requirements": [
"pyMetno==0.4.6"

View File

@ -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"
}
}
}

View File

@ -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):

View File

@ -32,6 +32,7 @@ FLOWS = [
"logi_circle",
"luftdaten",
"mailgun",
"met",
"mobile_app",
"mqtt",
"nest",

View File

@ -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