Add local_ip unique_id & icon and single_instance_allowed (#33483)

* Add config flow + sensor unique_id & icon to local_ip

* single_instance_allowed

* Fix test

* Martin's review

* Name deprecated
This commit is contained in:
Quentame 2020-04-09 16:06:01 +02:00 committed by GitHub
parent dd7fbef948
commit 45b28b8b00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 66 additions and 37 deletions

View File

@ -1,7 +1,7 @@
{
"config": {
"abort": {
"already_configured": "Integration is already configured with an existing sensor with that name"
"single_instance_allowed": "Only a single configuration of Local IP is allowed."
},
"step": {
"user": {

View File

@ -1,16 +1,20 @@
"""Get the local IP address of the Home Assistant instance."""
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
DOMAIN = "local_ip"
PLATFORM = "sensor"
from .const import DOMAIN, PLATFORM
CONFIG_SCHEMA = vol.Schema(
{DOMAIN: vol.Schema({vol.Optional(CONF_NAME, default=DOMAIN): cv.string})},
{
DOMAIN: vol.All(
cv.deprecated(CONF_NAME, invalidation_version="0.110"),
vol.Schema({vol.Optional(CONF_NAME, default=DOMAIN): cv.string}),
)
},
extra=vol.ALLOW_EXTRA,
)
@ -21,14 +25,14 @@ async def async_setup(hass: HomeAssistant, config: dict):
if conf:
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, data=conf, context={"source": config_entries.SOURCE_IMPORT}
DOMAIN, data=conf, context={"source": SOURCE_IMPORT}
)
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEntry):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up local_ip from a config entry."""
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, PLATFORM)
@ -37,6 +41,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEnt
return True
async def async_unload_entry(hass: HomeAssistant, entry: config_entries.ConfigEntry):
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
return await hass.config_entries.async_forward_entry_unload(entry, PLATFORM)

View File

@ -1,9 +1,8 @@
"""Config flow for local_ip."""
import voluptuous as vol
from homeassistant import config_entries
from . import DOMAIN
from .const import DOMAIN
class SimpleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
@ -14,20 +13,14 @@ class SimpleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
if user_input is not None:
if any(
user_input["name"] == entry.data["name"]
for entry in self._async_current_entries()
):
return self.async_abort(reason="already_configured")
return self.async_create_entry(title=user_input["name"], data=user_input)
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
return self.async_show_form(
step_id="user",
data_schema=vol.Schema({vol.Required("name", default=DOMAIN): str}),
errors={},
)
if user_input is None:
return self.async_show_form(step_id="user")
return self.async_create_entry(title=DOMAIN, data=user_input)
async def async_step_import(self, import_info):
"""Handle import from config file."""

View File

@ -0,0 +1,6 @@
"""Local IP constants."""
DOMAIN = "local_ip"
PLATFORM = "sensor"
SENSOR = "address"

View File

@ -1,20 +1,22 @@
"""Sensor platform for local_ip."""
from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_NAME
from homeassistant.helpers.entity import Entity
from homeassistant.util import get_local_ip
from .const import DOMAIN, SENSOR
async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the platform from config_entry."""
name = config_entry.data["name"]
name = config_entry.data.get(CONF_NAME) or DOMAIN
async_add_entities([IPSensor(name)], True)
class IPSensor(Entity):
"""A simple sensor."""
def __init__(self, name: str):
def __init__(self, name):
"""Initialize the sensor."""
self._state = None
self._name = name
@ -24,11 +26,21 @@ class IPSensor(Entity):
"""Return the name of the sensor."""
return self._name
@property
def unique_id(self):
"""Return the unique id of the sensor."""
return SENSOR
@property
def state(self):
"""Return the state of the sensor."""
return self._state
@property
def icon(self):
"""Return the icon of the sensor."""
return "mdi:ip"
def update(self):
"""Fetch new state data for the sensor."""
self._state = get_local_ip()

View File

@ -10,7 +10,7 @@
}
},
"abort": {
"already_configured": "Integration is already configured with an existing sensor with that name"
"single_instance_allowed": "Only a single configuration of Local IP is allowed."
}
}
}

View File

@ -1,19 +1,33 @@
"""Tests for the local_ip config_flow."""
from homeassistant.components.local_ip import DOMAIN
from homeassistant import data_entry_flow
from homeassistant.components.local_ip.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
from tests.common import MockConfigEntry
async def test_config_flow(hass):
"""Test we can finish a config flow."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == "form"
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"name": "test"}
)
assert result["type"] == "create_entry"
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
await hass.async_block_till_done()
state = hass.states.get("sensor.test")
state = hass.states.get(f"sensor.{DOMAIN}")
assert state
async def test_already_setup(hass):
"""Test we abort if already setup."""
MockConfigEntry(domain=DOMAIN, data={},).add_to_hass(hass)
# Should fail, same NAME
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "single_instance_allowed"

View File

@ -9,7 +9,7 @@ from homeassistant.util import get_local_ip
@pytest.fixture(name="config")
def config_fixture():
"""Create hass config fixture."""
return {DOMAIN: {"name": "test"}}
return {DOMAIN: {}}
async def test_basic_setup(hass, config):
@ -17,6 +17,6 @@ async def test_basic_setup(hass, config):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
local_ip = await hass.async_add_executor_job(get_local_ip)
state = hass.states.get("sensor.test")
state = hass.states.get(f"sensor.{DOMAIN}")
assert state
assert state.state == local_ip