Add HACS integration, 8 Lovelace cards, and pairing page
CI / Identify a merged version PR (push) Canceled after 0s
CI / Rust checks, rendering, and native package (push) Canceled after 0s
CI / Publish release and Homebrew feed (push) Canceled after 0s
Release PR / Maintain Version Packages PR (push) Canceled after 0s

New HA integration (integration/custom_components/luma_home/) with:
- WS API: luma/get_config (Lovelace→v2 bridge), luma/pair, luma/pair_status
- Config flow with dashboard URL path setting

8 HACS frontend cards (cards/) matching TV app visual spec:
- toggle, range, climate, media, curtain, action, vacuum, weather
- Glass card design: rgba(36,40,48,0.75) bg, 22px radius, accent glows

Pairing page (pairing/luma-pair.html) for TV token provisioning.
Web dashboard (web-dashboard/) — legacy config editor (deprecated).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kaloyan DanchevandClaude Opus 4.6 committed 2026-10-25 13:19:26 +02:00
1 parent a890ba6baf
commit d681f20884
18 files changed
+2708

No files matched your search

@@ -0,0 +1,66 @@
"""Config flow for Luma Home."""
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from .const import DOMAIN, CONF_DASHBOARD_URL_PATH, DEFAULT_DASHBOARD_URL_PATH
class LumaHomeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Luma Home."""
VERSION = 1
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")
if user_input is not None:
return self.async_create_entry(
title="Luma Home",
data=user_input,
)
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(
CONF_DASHBOARD_URL_PATH,
default=DEFAULT_DASHBOARD_URL_PATH,
): str,
}
),
)
@staticmethod
@callback
def async_get_options_flow(config_entry):
return LumaHomeOptionsFlow(config_entry)
class LumaHomeOptionsFlow(config_entries.OptionsFlow):
"""Handle options."""
def __init__(self, config_entry):
self.config_entry = config_entry
async def async_step_init(self, user_input=None):
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
return self.async_show_form(
step_id="init",
data_schema=vol.Schema(
{
vol.Required(
CONF_DASHBOARD_URL_PATH,
default=self.config_entry.data.get(
CONF_DASHBOARD_URL_PATH, DEFAULT_DASHBOARD_URL_PATH
),
): str,
}
),
)