Adjust OpenUV integration for upcoming API limit changes (#19949)
* Adjust OpenUV integration for upcoming API limit changes * Added fix for "Invalid API Key" * Bugfix * Add initial nighttime check * Move from polling to a service-based model * Fixed test * Removed unnecessary scan interval * Fixed test * Moving test imports * Member comments * Hound * Removed unused import
This commit is contained in:
parent
fff3cb0b46
commit
ef79566864
5 changed files with 60 additions and 71 deletions
|
@ -5,7 +5,6 @@ For more details about this component, please refer to the documentation at
|
|||
https://home-assistant.io/components/openuv/
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -13,15 +12,14 @@ from homeassistant.config_entries import SOURCE_IMPORT
|
|||
from homeassistant.const import (
|
||||
ATTR_ATTRIBUTION, CONF_API_KEY, CONF_BINARY_SENSORS, CONF_ELEVATION,
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_MONITORED_CONDITIONS,
|
||||
CONF_SCAN_INTERVAL, CONF_SENSORS)
|
||||
CONF_SENSORS)
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import aiohttp_client, config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
from .config_flow import configured_instances
|
||||
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN
|
||||
from .const import DOMAIN
|
||||
|
||||
REQUIREMENTS = ['pyopenuv==1.0.4']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -93,8 +91,6 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
vol.Optional(CONF_BINARY_SENSORS, default={}):
|
||||
BINARY_SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_SENSORS, default={}): SENSOR_SCHEMA,
|
||||
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL):
|
||||
cv.time_period,
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
@ -120,7 +116,6 @@ async def async_setup(hass, config):
|
|||
CONF_API_KEY: conf[CONF_API_KEY],
|
||||
CONF_BINARY_SENSORS: conf[CONF_BINARY_SENSORS],
|
||||
CONF_SENSORS: conf[CONF_SENSORS],
|
||||
CONF_SCAN_INTERVAL: conf[CONF_SCAN_INTERVAL],
|
||||
}
|
||||
|
||||
if CONF_LATITUDE in conf:
|
||||
|
@ -167,17 +162,13 @@ async def async_setup_entry(hass, config_entry):
|
|||
hass.config_entries.async_forward_entry_setup(
|
||||
config_entry, component))
|
||||
|
||||
async def refresh(event_time):
|
||||
async def update_data(service):
|
||||
"""Refresh OpenUV data."""
|
||||
_LOGGER.debug('Refreshing OpenUV data')
|
||||
await openuv.async_update()
|
||||
async_dispatcher_send(hass, TOPIC_UPDATE)
|
||||
|
||||
hass.data[DOMAIN][DATA_OPENUV_LISTENER][
|
||||
config_entry.entry_id] = async_track_time_interval(
|
||||
hass,
|
||||
refresh,
|
||||
timedelta(seconds=config_entry.data[CONF_SCAN_INTERVAL]))
|
||||
hass.services.async_register(DOMAIN, 'update_data', update_data)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -186,10 +177,6 @@ async def async_unload_entry(hass, config_entry):
|
|||
"""Unload an OpenUV config entry."""
|
||||
hass.data[DOMAIN][DATA_OPENUV_CLIENT].pop(config_entry.entry_id)
|
||||
|
||||
remove_listener = hass.data[DOMAIN][DATA_OPENUV_LISTENER].pop(
|
||||
config_entry.entry_id)
|
||||
remove_listener()
|
||||
|
||||
for component in ('binary_sensor', 'sensor'):
|
||||
await hass.config_entries.async_forward_entry_unload(
|
||||
config_entry, component)
|
||||
|
|
|
@ -5,11 +5,10 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY, CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE,
|
||||
CONF_SCAN_INTERVAL)
|
||||
CONF_API_KEY, CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE)
|
||||
from homeassistant.helpers import aiohttp_client, config_validation as cv
|
||||
|
||||
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -54,7 +53,8 @@ class OpenUvFlowHandler(config_entries.ConfigFlow):
|
|||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the start of the config flow."""
|
||||
from pyopenuv.util import validate_api_key
|
||||
from pyopenuv import Client
|
||||
from pyopenuv.errors import OpenUvError
|
||||
|
||||
if not user_input:
|
||||
return await self._show_form()
|
||||
|
@ -66,14 +66,11 @@ class OpenUvFlowHandler(config_entries.ConfigFlow):
|
|||
return await self._show_form({CONF_LATITUDE: 'identifier_exists'})
|
||||
|
||||
websession = aiohttp_client.async_get_clientsession(self.hass)
|
||||
api_key_validation = await validate_api_key(
|
||||
user_input[CONF_API_KEY], websession)
|
||||
client = Client(user_input[CONF_API_KEY], 0, 0, websession)
|
||||
|
||||
if not api_key_validation:
|
||||
try:
|
||||
await client.uv_index()
|
||||
except OpenUvError:
|
||||
return await self._show_form({CONF_API_KEY: 'invalid_api_key'})
|
||||
|
||||
scan_interval = user_input.get(
|
||||
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||
user_input[CONF_SCAN_INTERVAL] = scan_interval.seconds
|
||||
|
||||
return self.async_create_entry(title=identifier, data=user_input)
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
"""Define constants for the OpenUV component."""
|
||||
from datetime import timedelta
|
||||
|
||||
DOMAIN = 'openuv'
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = timedelta(minutes=30)
|
||||
|
|
5
homeassistant/components/openuv/services.yaml
Normal file
5
homeassistant/components/openuv/services.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Describes the format for available OpenUV services
|
||||
|
||||
---
|
||||
update_data:
|
||||
description: Request new data from OpenUV.
|
|
@ -1,14 +1,27 @@
|
|||
"""Define tests for the OpenUV config flow."""
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
import pytest
|
||||
from pyopenuv.errors import OpenUvError
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.openuv import DOMAIN, config_flow
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY, CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE,
|
||||
CONF_SCAN_INTERVAL)
|
||||
CONF_API_KEY, CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE)
|
||||
|
||||
from tests.common import MockConfigEntry, mock_coro
|
||||
from tests.common import MockConfigEntry, MockDependency, mock_coro
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def uv_index_response():
|
||||
"""Define a fixture for a successful /uv response."""
|
||||
return mock_coro()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_pyopenuv(uv_index_response):
|
||||
"""Mock the pyopenuv library."""
|
||||
with MockDependency('pyopenuv') as mock_pyopenuv_:
|
||||
mock_pyopenuv_.Client().uv_index.return_value = uv_index_response
|
||||
yield mock_pyopenuv_
|
||||
|
||||
|
||||
async def test_duplicate_error(hass):
|
||||
|
@ -28,7 +41,9 @@ async def test_duplicate_error(hass):
|
|||
assert result['errors'] == {CONF_LATITUDE: 'identifier_exists'}
|
||||
|
||||
|
||||
async def test_invalid_api_key(hass):
|
||||
@pytest.mark.parametrize(
|
||||
'uv_index_response', [mock_coro(exception=OpenUvError)])
|
||||
async def test_invalid_api_key(hass, mock_pyopenuv):
|
||||
"""Test that an invalid API key throws an error."""
|
||||
conf = {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
|
@ -40,10 +55,8 @@ async def test_invalid_api_key(hass):
|
|||
flow = config_flow.OpenUvFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
with patch('pyopenuv.util.validate_api_key',
|
||||
return_value=mock_coro(False)):
|
||||
result = await flow.async_step_user(user_input=conf)
|
||||
assert result['errors'] == {CONF_API_KEY: 'invalid_api_key'}
|
||||
result = await flow.async_step_user(user_input=conf)
|
||||
assert result['errors'] == {CONF_API_KEY: 'invalid_api_key'}
|
||||
|
||||
|
||||
async def test_show_form(hass):
|
||||
|
@ -57,7 +70,7 @@ async def test_show_form(hass):
|
|||
assert result['step_id'] == 'user'
|
||||
|
||||
|
||||
async def test_step_import(hass):
|
||||
async def test_step_import(hass, mock_pyopenuv):
|
||||
"""Test that the import step works."""
|
||||
conf = {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
|
@ -69,44 +82,35 @@ async def test_step_import(hass):
|
|||
flow = config_flow.OpenUvFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
with patch('pyopenuv.util.validate_api_key',
|
||||
return_value=mock_coro(True)):
|
||||
result = await flow.async_step_import(import_config=conf)
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result['title'] == '39.128712, -104.9812612'
|
||||
assert result['data'] == {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
CONF_ELEVATION: 59.1234,
|
||||
CONF_LATITUDE: 39.128712,
|
||||
CONF_LONGITUDE: -104.9812612,
|
||||
CONF_SCAN_INTERVAL: 1800,
|
||||
}
|
||||
result = await flow.async_step_import(import_config=conf)
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result['title'] == '39.128712, -104.9812612'
|
||||
assert result['data'] == {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
CONF_ELEVATION: 59.1234,
|
||||
CONF_LATITUDE: 39.128712,
|
||||
CONF_LONGITUDE: -104.9812612,
|
||||
}
|
||||
|
||||
|
||||
async def test_step_user(hass):
|
||||
async def test_step_user(hass, mock_pyopenuv):
|
||||
"""Test that the user step works."""
|
||||
conf = {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
CONF_ELEVATION: 59.1234,
|
||||
CONF_LATITUDE: 39.128712,
|
||||
CONF_LONGITUDE: -104.9812612,
|
||||
CONF_SCAN_INTERVAL: timedelta(minutes=5)
|
||||
}
|
||||
|
||||
flow = config_flow.OpenUvFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
with patch('pyopenuv.util.validate_api_key',
|
||||
return_value=mock_coro(True)):
|
||||
result = await flow.async_step_user(user_input=conf)
|
||||
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result['title'] == '39.128712, -104.9812612'
|
||||
assert result['data'] == {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
CONF_ELEVATION: 59.1234,
|
||||
CONF_LATITUDE: 39.128712,
|
||||
CONF_LONGITUDE: -104.9812612,
|
||||
CONF_SCAN_INTERVAL: 300,
|
||||
}
|
||||
result = await flow.async_step_user(user_input=conf)
|
||||
assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result['title'] == '39.128712, -104.9812612'
|
||||
assert result['data'] == {
|
||||
CONF_API_KEY: '12345abcde',
|
||||
CONF_ELEVATION: 59.1234,
|
||||
CONF_LATITUDE: 39.128712,
|
||||
CONF_LONGITUDE: -104.9812612,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue