Add config flow to ISS integration ()

* Initial commit

* Wrong flowhandler name

* Add config flow tests

* Tests for config flow

* ...

* Add test for no coordinates

* ...

* Update homeassistant/components/iss/config_flow.py

Co-authored-by: Shay Levy <levyshay1@gmail.com>

* Update homeassistant/components/iss/config_flow.py

* Update homeassistant/components/iss/binary_sensor.py

Co-authored-by: Shay Levy <levyshay1@gmail.com>

* Add myself as codeowner

Co-authored-by: Shay Levy <levyshay1@gmail.com>
pull/65183/head
Simon Hansen 2022-01-29 10:41:26 +01:00 committed by GitHub
parent 3cde472e43
commit 049fc8a945
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 228 additions and 11 deletions

View File

@ -520,6 +520,7 @@ omit =
homeassistant/components/iperf3/*
homeassistant/components/iqvia/*
homeassistant/components/irish_rail_transport/sensor.py
homeassistant/components/iss/__init__.py
homeassistant/components/iss/binary_sensor.py
homeassistant/components/isy994/__init__.py
homeassistant/components/isy994/binary_sensor.py

View File

@ -467,6 +467,8 @@ tests/components/iqvia/* @bachya
homeassistant/components/irish_rail_transport/* @ttroy50
homeassistant/components/islamic_prayer_times/* @engrbm87
tests/components/islamic_prayer_times/* @engrbm87
homeassistant/components/iss/* @DurgNomis-drol
tests/components/iss/* @DurgNomis-drol
homeassistant/components/isy994/* @bdraco @shbatm
tests/components/isy994/* @bdraco @shbatm
homeassistant/components/izone/* @Swamp-Ig

View File

@ -1 +1,27 @@
"""The iss component."""
from __future__ import annotations
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from .const import DOMAIN
PLATFORMS = [Platform.BINARY_SENSOR]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up this integration using UI."""
hass.data.setdefault(DOMAIN, {})
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Handle removal of an entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
del hass.data[DOMAIN]
return unload_ok

View File

@ -1,4 +1,4 @@
"""Support for International Space Station binary sensor."""
"""Support for iss binary sensor."""
from __future__ import annotations
from datetime import timedelta
@ -10,6 +10,7 @@ from requests.exceptions import HTTPError
import voluptuous as vol
from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorEntity
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import (
ATTR_LATITUDE,
ATTR_LONGITUDE,
@ -22,6 +23,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import Throttle
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
ATTR_ISS_NEXT_RISE = "next_rise"
@ -46,22 +49,40 @@ def setup_platform(
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the ISS binary sensor."""
if None in (hass.config.latitude, hass.config.longitude):
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
return
"""Import ISS configuration from yaml."""
_LOGGER.warning(
"Configuration of the iss platform in YAML is deprecated and will be "
"removed in Home Assistant 2022.5; Your existing configuration "
"has been imported into the UI automatically and can be safely removed "
"from your configuration.yaml file"
)
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=config,
)
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the sensor platform."""
name = entry.data.get(CONF_NAME, DEFAULT_NAME)
show_on_map = entry.data.get(CONF_SHOW_ON_MAP, False)
try:
iss_data = IssData(hass.config.latitude, hass.config.longitude)
iss_data.update()
await hass.async_add_executor_job(iss_data.update)
except HTTPError as error:
_LOGGER.error(error)
return
name = config.get(CONF_NAME)
show_on_map = config.get(CONF_SHOW_ON_MAP)
add_entities([IssBinarySensor(iss_data, name, show_on_map)], True)
async_add_entities([IssBinarySensor(iss_data, name, show_on_map)], True)
class IssBinarySensor(BinarySensorEntity):

View File

@ -0,0 +1,48 @@
"""Config flow to configure iss component."""
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_NAME, CONF_SHOW_ON_MAP
from homeassistant.data_entry_flow import FlowResult
from .const import DOMAIN
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Config flow for iss component."""
VERSION = 1
async def async_step_user(self, user_input=None) -> FlowResult:
"""Handle a flow initialized by the user."""
# Check if already configured
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
# Check if location have been defined.
if not self.hass.config.latitude and not self.hass.config.longitude:
return self.async_abort(reason="latitude_longitude_not_defined")
if user_input is not None:
return self.async_create_entry(
title="International Space Station", data=user_input
)
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Optional(CONF_SHOW_ON_MAP, default=False): bool,
}
),
)
async def async_step_import(self, conf: dict) -> FlowResult:
"""Import a configuration from configuration.yaml."""
return await self.async_step_user(
user_input={
CONF_NAME: conf[CONF_NAME],
CONF_SHOW_ON_MAP: conf[CONF_SHOW_ON_MAP],
}
)

View File

@ -0,0 +1,3 @@
"""Constants for iss."""
DOMAIN = "iss"

View File

@ -1,9 +1,10 @@
{
"domain": "iss",
"config_flow": true,
"name": "International Space Station (ISS)",
"documentation": "https://www.home-assistant.io/integrations/iss",
"requirements": ["pyiss==1.0.1"],
"codeowners": [],
"codeowners": ["@DurgNomis-drol"],
"iot_class": "cloud_polling",
"loggers": ["pyiss"]
}

View File

@ -0,0 +1,16 @@
{
"config": {
"step": {
"user": {
"description": "Do you want to configure the Internation Space Station?",
"data": {
"show_on_map": "Show on map?"
}
}
},
"abort": {
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
"latitude_longitude_not_defined": "Latitude and longitude is not defind in Home Assistant."
}
}
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"latitude_longitude_not_defined": "Latitude and longitude is not defind in Home Assistant.",
"single_instance_allowed": "Already configured. Only a single configuration possible."
},
"step": {
"user": {
"data": {
"show_on_map": "Show on map?"
},
"description": "Do you want to configure the Internation Space Station?"
}
}
}
}

View File

@ -159,6 +159,7 @@ FLOWS = [
"ipp",
"iqvia",
"islamic_prayer_times",
"iss",
"isy994",
"izone",
"jellyfin",

View File

@ -998,6 +998,9 @@ pyipp==0.11.0
# homeassistant.components.iqvia
pyiqvia==2021.11.0
# homeassistant.components.iss
pyiss==1.0.1
# homeassistant.components.isy994
pyisy==3.0.1

View File

@ -0,0 +1 @@
"""Tests for the iss component."""

View File

@ -0,0 +1,78 @@
"""Test iss config flow."""
from unittest.mock import patch
from homeassistant import data_entry_flow
from homeassistant.components.iss.binary_sensor import DEFAULT_NAME
from homeassistant.components.iss.const import DOMAIN
from homeassistant.config import async_process_ha_core_config
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
from homeassistant.const import CONF_NAME, CONF_SHOW_ON_MAP
from tests.common import MockConfigEntry
async def test_import(hass):
"""Test entry will be imported."""
imported_config = {CONF_NAME: DEFAULT_NAME, CONF_SHOW_ON_MAP: False}
with patch("homeassistant.components.iss.async_setup_entry", return_value=True):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=imported_config
)
assert result.get("type") == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result.get("result").data == imported_config
async def test_create_entry(hass):
"""Test we can finish a config flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result.get("type") == data_entry_flow.RESULT_TYPE_FORM
assert result.get("step_id") == SOURCE_USER
with patch("homeassistant.components.iss.async_setup_entry", return_value=True):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_SHOW_ON_MAP: True},
)
assert result.get("type") == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result.get("result").data[CONF_SHOW_ON_MAP] is True
async def test_integration_already_exists(hass):
"""Test we only allow a single config flow."""
MockConfigEntry(
domain=DOMAIN,
data={},
).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data={CONF_SHOW_ON_MAP: False}
)
assert result.get("type") == data_entry_flow.RESULT_TYPE_ABORT
assert result.get("reason") == "single_instance_allowed"
async def test_abort_no_home(hass):
"""Test we don't create an entry if no coordinates are set."""
await async_process_ha_core_config(
hass,
{"latitude": 0.0, "longitude": 0.0},
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data={CONF_SHOW_ON_MAP: False}
)
assert result.get("type") == data_entry_flow.RESULT_TYPE_ABORT
assert result.get("reason") == "latitude_longitude_not_defined"