Update changelog for version 0.1.5, add automatic Lovelace resource registration, and enhance chat card functionality

This commit is contained in:
techartdev
2026-02-20 14:37:00 +02:00
parent 793ea1488f
commit 2308ddfc45
5 changed files with 971 additions and 23 deletions
+93 -20
View File
@@ -40,8 +40,25 @@ from .coordinator import OpenClawCoordinator
_LOGGER = logging.getLogger(__name__)
# Path to the chat card JS inside the integration package (custom_components/openclaw/www/)
_CARD_FILENAME = "openclaw-chat-card.js"
_CARD_PATH = Path(__file__).parent / "www" / _CARD_FILENAME
# URL at which the card JS will be served (registered via register_static_path)
_CARD_URL = f"/openclaw/{_CARD_FILENAME}"
type OpenClawConfigEntry = ConfigEntry
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
"""Global integration setup — runs once before any config entries.
Registers the static HTTP path for the chat card so the JS file is served
directly from inside the integration package, regardless of whether the
user installed via HACS or manually.
"""
_async_register_static_path(hass)
return True
# Service call schemas
SEND_MESSAGE_SCHEMA = vol.Schema(
{
@@ -57,9 +74,6 @@ CLEAR_HISTORY_SCHEMA = vol.Schema(
}
)
# Path to the chat card JS inside the integration
_CARD_FILENAME = "openclaw-chat-card.js"
async def async_setup_entry(hass: HomeAssistant, entry: OpenClawConfigEntry) -> bool:
"""Set up OpenClaw from a config entry.
@@ -164,31 +178,90 @@ def _async_setup_token_refresh(
# ── Frontend registration ─────────────────────────────────────────────────────
@callback
def _async_register_frontend(hass: HomeAssistant) -> None:
"""Register the Lovelace custom card resource.
def _async_register_static_path(hass: HomeAssistant) -> None:
"""Register the integration's www/ folder as a static HTTP path.
Attempts to register as a Lovelace module resource so the card
is available without manual YAML edits. Falls back to a log hint
if programmatic registration isn't possible.
After this the card JS is always available at /openclaw/openclaw-chat-card.js
regardless of how the integration was installed (HACS or manual).
"""
static_key = f"{DOMAIN}_static_registered"
if hass.data.get(static_key):
return
hass.data[static_key] = True
if not _CARD_PATH.exists():
_LOGGER.warning(
"Chat card JS not found at %s — frontend resource will not be available",
_CARD_PATH,
)
return
hass.http.register_static_path(
f"/openclaw/{_CARD_FILENAME}",
str(_CARD_PATH),
cache_headers=True,
)
_LOGGER.debug("Registered static path: /openclaw/%s", _CARD_FILENAME)
@callback
def _async_register_frontend(hass: HomeAssistant) -> None:
"""Register the Lovelace custom card resource (called once per setup).
Adds the card URL to Lovelace's resource list so it loads on every
dashboard automatically. No manual step required.
"""
frontend_key = f"{DOMAIN}_frontend_registered"
if hass.data.get(frontend_key):
return
hass.data[frontend_key] = True
# The card JS is distributed in www/ alongside the integration.
# Users install via HACS which symlinks it into config/www/community/openclaw/
# or manually copy to config/www/.
# We register the resource URL so it auto-loads.
url = f"/local/community/openclaw/{_CARD_FILENAME}"
# Ensure static path is registered (may have been missed if async_setup
# didn't run, e.g. during a config entry reload).
_async_register_static_path(hass)
# Static path registration is handled by HACS for HACS installs,
# or manually by the user. We just log the expected URL.
_LOGGER.info(
"OpenClaw chat card: add as a Lovelace resource at '%s' "
"(type: JavaScript Module). HACS does this automatically.",
url,
)
hass.async_create_task(_async_add_lovelace_resource(hass, _CARD_URL))
async def _async_add_lovelace_resource(hass: HomeAssistant, url: str) -> None:
"""Add the card URL to Lovelace's resource store if not already present."""
# Lovelace stores resources in hass.data["lovelace"]["resources"].
# It is a ResourceStorageCollection with:
# .async_items() → list of {"id", "res_type", "url"} dicts
# .async_create_item(data) → persists a new resource
lovelace_data = hass.data.get("lovelace")
if not lovelace_data:
_LOGGER.debug(
"Lovelace not loaded; resource '%s' must be added manually if needed",
url,
)
return
resource_collection = lovelace_data.get("resources")
if resource_collection is None:
_LOGGER.debug("Lovelace resource store not available")
return
try:
existing_urls = {item["url"] for item in resource_collection.async_items()}
if url in existing_urls:
_LOGGER.debug("Lovelace resource already registered: %s", url)
return
await resource_collection.async_create_item(
{"res_type": "module", "url": url}
)
_LOGGER.info(
"Auto-registered Lovelace resource: %s — the chat card is ready to use.",
url,
)
except Exception as err: # noqa: BLE001
_LOGGER.warning(
"Could not auto-register Lovelace resource '%s': %s. "
"Add it manually: Settings → Dashboards → Resources.",
url,
err,
)
# ── Service registration ──────────────────────────────────────────────────────