Add files via upload

This commit is contained in:
thekiwismarthome
2026-02-13 10:31:02 +13:00
committed by GitHub
parent 9022ed0dc8
commit b6bfa78eb5
@@ -1,56 +1,173 @@
""" """Shopping List Manager integration for Home Assistant."""
Shopping List Manager - Home Assistant Custom Integration
Clean-slate architecture with enforced invariants
"""
import logging import logging
import os
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.components import websocket_api as ha_websocket from homeassistant.helpers.typing import ConfigType
from .websocket_api import websocket_create_list
from .const import DOMAIN from .const import DOMAIN
from .manager import ShoppingListManager from .storage import ShoppingListStorage
# Import websocket handler functions directly
from .websocket_api import (
websocket_add_product,
websocket_set_qty,
websocket_get_products,
websocket_get_active,
websocket_delete_product,
ws_get_catalogues,
ws_get_lists,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# Track storage instance globally
DATA_STORAGE = f"{DOMAIN}_storage"
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Shopping List Manager component from yaml (not used)."""
# This integration doesn't support YAML configuration
# All setup is done via config entries (UI configuration)
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Shopping List Manager from a config entry.""" """Set up Shopping List Manager from a config entry."""
# Initialize the manager _LOGGER.info("Setting up Shopping List Manager")
manager = ShoppingListManager(hass)
await manager.async_load()
# Store manager in hass.data # Get component path for loading data files
component_path = os.path.dirname(__file__)
# Initialize storage
storage = ShoppingListStorage(hass, component_path)
await storage.async_load()
# Store storage instance in hass.data
hass.data.setdefault(DOMAIN, {}) hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN]["manager"] = manager hass.data[DOMAIN][DATA_STORAGE] = storage
# Register WebSocket commands using Home Assistant's websocket_api # Register WebSocket commands
ha_websocket.async_register_command(hass, websocket_create_list) await _async_register_websocket_handlers(hass, storage)
ha_websocket.async_register_command(hass, websocket_add_product)
ha_websocket.async_register_command(hass, websocket_set_qty)
ha_websocket.async_register_command(hass, websocket_get_products)
ha_websocket.async_register_command(hass, websocket_get_active)
ha_websocket.async_register_command(hass, websocket_delete_product)
ha_websocket.async_register_command(hass, ws_get_catalogues)
ha_websocket.async_register_command(hass, ws_get_lists)
_LOGGER.info("Shopping List Manager setup complete - registered 7 WebSocket commands") # Register frontend resources
await _async_register_frontend(hass)
_LOGGER.info("Shopping List Manager setup complete")
return True return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload Shopping List Manager.""" """Unload a config entry."""
hass.data[DOMAIN].pop("manager", None) _LOGGER.info("Unloading Shopping List Manager")
# Clean up hass.data
if DOMAIN in hass.data:
hass.data[DOMAIN].pop(DATA_STORAGE, None)
return True return True
async def _async_register_websocket_handlers(
hass: HomeAssistant,
storage: ShoppingListStorage
) -> None:
"""Register WebSocket API handlers."""
from homeassistant.components import websocket_api
from .websocket import handlers
# Lists handlers
websocket_api.async_register_command(
hass,
handlers.websocket_get_lists,
)
websocket_api.async_register_command(
hass,
handlers.websocket_create_list,
)
websocket_api.async_register_command(
hass,
handlers.websocket_update_list,
)
websocket_api.async_register_command(
hass,
handlers.websocket_delete_list,
)
websocket_api.async_register_command(
hass,
handlers.websocket_set_active_list,
)
# Items handlers
websocket_api.async_register_command(
hass,
handlers.websocket_get_items,
)
websocket_api.async_register_command(
hass,
handlers.websocket_add_item,
)
websocket_api.async_register_command(
hass,
handlers.websocket_update_item,
)
websocket_api.async_register_command(
hass,
handlers.websocket_check_item,
)
websocket_api.async_register_command(
hass,
handlers.websocket_delete_item,
)
websocket_api.async_register_command(
hass,
handlers.websocket_reorder_items,
)
websocket_api.async_register_command(
hass,
handlers.websocket_bulk_check_items,
)
websocket_api.async_register_command(
hass,
handlers.websocket_clear_checked_items,
)
websocket_api.async_register_command(
hass,
handlers.websocket_get_list_total,
)
# Products handlers
websocket_api.async_register_command(
hass,
handlers.websocket_search_products,
)
websocket_api.async_register_command(
hass,
handlers.websocket_get_product_suggestions,
)
websocket_api.async_register_command(
hass,
handlers.websocket_add_product,
)
websocket_api.async_register_command(
hass,
handlers.websocket_update_product,
)
# Categories handlers
websocket_api.async_register_command(
hass,
handlers.websocket_get_categories,
)
_LOGGER.debug("WebSocket handlers registered")
async def _async_register_frontend(hass: HomeAssistant) -> None:
"""Register frontend resources."""
# Register the custom card
hass.http.register_static_path(
f"/hacsfiles/{DOMAIN}",
hass.config.path(f"custom_components/{DOMAIN}/www"),
True,
)
_LOGGER.debug("Frontend resources registered")
def get_storage(hass: HomeAssistant) -> ShoppingListStorage:
"""Get the storage instance from hass.data.
Helper function for WebSocket handlers to access storage.
"""
return hass.data[DOMAIN][DATA_STORAGE]