Handle ESPHome dashboard discovery (#85662)

This commit is contained in:
Paulus Schoutsen 2023-01-11 08:30:52 -05:00 committed by GitHub
parent 1a4cac95a1
commit 82ec769ec5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 3 deletions

View File

@ -56,6 +56,7 @@ from homeassistant.helpers.service import async_set_service_schema
from homeassistant.helpers.template import Template
from .bluetooth import async_connect_scanner
from .dashboard import async_get_dashboard
from .domain_data import DOMAIN, DomainData
# Import config flow so that it's added to the registry
@ -352,6 +353,8 @@ def _async_setup_device_registry(
configuration_url = None
if device_info.webserver_port > 0:
configuration_url = f"http://{entry.data['host']}:{device_info.webserver_port}"
elif dashboard := async_get_dashboard(hass):
configuration_url = f"homeassistant://hassio/ingress/{dashboard.addon_slug}"
manufacturer = "espressif"
if device_info.manufacturer:

View File

@ -17,6 +17,7 @@ from aioesphomeapi import (
import voluptuous as vol
from homeassistant.components import dhcp, zeroconf
from homeassistant.components.hassio.discovery import HassioServiceInfo
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_PORT
from homeassistant.core import callback
@ -24,6 +25,7 @@ from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.device_registry import format_mac
from . import CONF_NOISE_PSK, DOMAIN
from .dashboard import async_set_dashboard_info
ERROR_REQUIRES_ENCRYPTION_KEY = "requires_encryption_key"
ESPHOME_URL = "https://esphome.io/"
@ -173,6 +175,16 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN):
# for configured devices.
return self.async_abort(reason="already_configured")
async def async_step_hassio(self, discovery_info: HassioServiceInfo) -> FlowResult:
"""Handle Supervisor service discovery."""
async_set_dashboard_info(
self.hass,
discovery_info.slug,
discovery_info.config["host"],
discovery_info.config["port"],
)
return self.async_abort(reason="service_received")
@callback
def _async_get_entry(self) -> FlowResult:
config_data = {

View File

@ -0,0 +1,28 @@
"""Files to interact with a the ESPHome dashboard."""
from __future__ import annotations
from dataclasses import dataclass
from homeassistant.core import HomeAssistant, callback
KEY_DASHBOARD = "esphome_dashboard"
@callback
def async_get_dashboard(hass: HomeAssistant) -> ESPHomeDashboard | None:
"""Get an instance of the dashboard if set."""
return hass.data.get(KEY_DASHBOARD)
def async_set_dashboard_info(
hass: HomeAssistant, addon_slug: str, _host: str, _port: int
) -> None:
"""Set the dashboard info."""
hass.data[KEY_DASHBOARD] = ESPHomeDashboard(addon_slug)
@dataclass
class ESPHomeDashboard:
"""Class to interact with the ESPHome dashboard."""
addon_slug: str

View File

@ -4,7 +4,8 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"mdns_missing_mac": "Missing MAC address in MDNS properties."
"mdns_missing_mac": "Missing MAC address in MDNS properties.",
"service_received": "Service received"
},
"error": {
"resolve_error": "Can't resolve address of the ESP. If this error persists, please set a static IP address",

View File

@ -11,9 +11,15 @@ from aioesphomeapi import (
)
import pytest
from homeassistant import config_entries
from homeassistant import config_entries, data_entry_flow
from homeassistant.components import dhcp, zeroconf
from homeassistant.components.esphome import CONF_NOISE_PSK, DOMAIN, DomainData
from homeassistant.components.esphome import (
CONF_NOISE_PSK,
DOMAIN,
DomainData,
dashboard,
)
from homeassistant.components.hassio import HassioServiceInfo
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT
from homeassistant.data_entry_flow import FlowResultType
@ -620,3 +626,26 @@ async def test_discovery_dhcp_no_changes(hass, mock_client):
assert result["reason"] == "already_configured"
assert entry.data[CONF_HOST] == "192.168.43.183"
async def test_discovery_hassio(hass):
"""Test dashboard discovery."""
result = await hass.config_entries.flow.async_init(
"esphome",
data=HassioServiceInfo(
config={
"host": "mock-esphome",
"port": 6052,
},
name="ESPHome",
slug="mock-slug",
),
context={"source": config_entries.SOURCE_HASSIO},
)
assert result
assert result["type"] == data_entry_flow.FlowResultType.ABORT
assert result["reason"] == "service_received"
dash = dashboard.async_get_dashboard(hass)
assert dash is not None
assert dash.addon_slug == "mock-slug"