Espex.Wizard.Document (espex v0.12.0)

Copy Markdown View Source

The device wizard: the pages Home Assistant shows when the device is added. Build it with new/1 and return it from Espex.Wizard.wizard/0.

alias Espex.Wizard.{Document, Entity, EntityFilter, Input, Page}

Document.new!(
  pages: [
    %Page{
      title: "Calendars",
      description: "Pick the calendars to show on the display.",
      inputs: [
        %Input{
          id: "calendars",
          multiple: true,
          entity_filters: [%EntityFilter{domain: ["calendar"]}]
        }
      ]
    },
    %Page{
      title: "Backlight",
      entities: [%Entity{key: 1001, description: "Turn it on to test the display."}]
    }
  ]
)

new/1 checks the document against ESPHome's limits, so a mistake shows up when the host builds it rather than when a client connects:

  • at least one page, and each page has an entity or an input
  • page titles up to 127 bytes, descriptions up to 255
  • each filter sets at least one field; filter strings are 1-63 bytes, supported_features entries 1-127
  • max_length is 255-4095 and only on a multiple: true input
  • links only on an input without multiple, and each without an entity_id (see "Linked inputs" in Espex.Wizard.Input)
  • input ids are unique and their hashes do not collide
  • the compressed document fits one API message (65511 bytes)

It also fills each input's key from its id, and turns each link into an Espex.HomeAssistantStates.Subscription. Links stay on the device: the JSON sent to the client does not carry them. A %Document{} built as a struct without new/1 is run through it when a connection is accepted.

Strings are passed to Home Assistant verbatim, so they may be translation placeholders such as "[%key:component::light::title%]".

On the wire the document is compact UTF-8 JSON, version 1, compressed into one zstd frame. Empty and unset values are left out. Building it needs OTP 28 or newer for :zstd.

Summary

Functions

Build and check a document from pages:, a list of Espex.Wizard.Page structs. Returns {:error, message} naming the first problem.

Like new/1, but raises ArgumentError on a problem.

The document as sent in DeviceWizardResponse.data: compact JSON in one zstd frame. Built once by new/1.

Types

t()

(since 0.12.0)
@type t() :: %Espex.Wizard.Document{
  blob: binary() | nil,
  pages: [Espex.Wizard.Page.t()]
}

Functions

new(opts)

(since 0.12.0)
@spec new(keyword()) :: {:ok, t()} | {:error, String.t()}

Build and check a document from pages:, a list of Espex.Wizard.Page structs. Returns {:error, message} naming the first problem.

new!(opts)

(since 0.12.0)
@spec new!(keyword()) :: t()

Like new/1, but raises ArgumentError on a problem.

to_blob(document)

(since 0.12.0)
@spec to_blob(t()) :: binary()

The document as sent in DeviceWizardResponse.data: compact JSON in one zstd frame. Built once by new/1.