defmodule Hassock do @moduledoc """ Home Assistant WebSocket client for Elixir. Two layers, opt-in: * `Hassock.Connection` — the WebSocket itself. Always required. * `Hassock.Cache` — optional ETS-backed full entity cache, kept in sync via HA's `subscribe_entities` command. Both follow the controlling-process pattern (à la `:gen_tcp`, `Circuits.UART`): the process that calls `start_link/1` is the default recipient of async messages. Use `controlling_process/2` to hand off. ## Bare connection {:ok, conn} = Hassock.connect( config: %Hassock.Config{url: "http://homeassistant.local:8123", token: "..."} ) receive do {:hassock, ^conn, :connected} -> :ok end {:ok, sub} = Hassock.subscribe_entities(conn, ["light.kitchen"]) # handle {:hassock, ^conn, {:event, {:entities, _}}} in your handle_info/2 ## With entity cache {:ok, conn} = Hassock.connect(config: config) {:ok, cache} = Hassock.Cache.start_link(connection: conn) receive do {:hassock_cache, ^cache, :ready} -> :ok end Hassock.cached_state(cache, "light.kitchen") """ alias Hassock.{Cache, Connection} @doc "Open a WebSocket connection. See `Hassock.Connection.start_link/1`." defdelegate connect(opts), to: Connection, as: :start_link @doc "Transfer connection ownership." defdelegate controlling_process(conn, pid), to: Connection @doc "Subscribe to entity state updates. Pass `nil` for all entities." defdelegate subscribe_entities(conn, entity_ids \\ nil), to: Connection @doc "Subscribe to a non-entity HA event type." defdelegate subscribe_events(conn, event_type), to: Connection @doc "Cancel a subscription." defdelegate unsubscribe_events(conn, subscription_id), to: Connection @doc "Call a Home Assistant service." defdelegate call_service(conn, service_call), to: Connection @doc "One-shot fetch of all entity states." defdelegate get_states(conn), to: Connection @doc "Fetch all available service domains and their services." defdelegate get_services(conn), to: Connection @doc "True if the connection is authenticated and the socket is open." defdelegate connected?(conn), to: Connection @doc "Look up a cached entity by id (requires a `Hassock.Cache`)." defdelegate cached_state(cache, entity_id), to: Cache, as: :get @doc "All cached entities." defdelegate cached_states(cache), to: Cache, as: :get_all @doc "All cached entities under a domain prefix (e.g. `\"light\"`)." defdelegate cached_domain(cache, domain), to: Cache, as: :get_domain end