BB.TUI.Renderer behaviour (BB.TUI v0.3.0)

Copy Markdown View Source

Behaviour a consumer implements to teach the dashboard how to render a payload on a PubSub path the consumer owns — without bb_tui knowing anything about that payload's shape or struct.

bb_tui subscribes to whatever paths it is told (:subscribe_paths) and dispatches each {:bb, path, msg} by path prefix. Most prefixes have dedicated, built-in handling ([:state_machine], [:sensor], [:param], …). Anything else falls to a generic event-log row via inspect/2.

A renderer plugs into that generic seam: a consumer registers a module for a path prefix via the :renderers option (a %{prefix => module} map threaded through BB.TUI.run/2, start/2, start_ssh/2). When a message arrives whose path matches a registered prefix (longest prefix wins, like a routing table), bb_tui calls back into the consumer's module rather than pattern-matching the payload itself. The dashboard therefore stays free of any downstream struct knowledge — the consumer owns the rendering of its own data.

Two callbacks:

  • summarize/2 — the one-line string for the event log. Return nil to fall back to bb_tui's generic inspect/2.
  • observed/2 (optional) — feed the at-a-glance status-bar readout. Return a {slot_key, display, meta} triple to record/refresh a slot, or nil to skip. The status bar surfaces the freshest slot (max meta.seq) and dims stale ones (meta.freshness == :stale).

Return shapes

summarize(path, payload)String.t() | nil.

observed(path, payload){slot_key, display, meta} | nil where:

  • slot_key — any term that identifies the slot (e.g. {:wheels, :imu} or a bare atom). Successive samples on the same slot_key overwrite, so the readout shows the latest value of each slot rather than accumulating.
  • display — a map() the status bar renders. bb_tui reads at least :label (a String.t() shown in the segment) from it; consumers may carry extra fields for their own future use.
  • meta — a map() carrying at least:
    • :freshness:fresh | :stale. Stale slots render dimmed.

    • :seq — a sortable term (typically an integer or timestamp). The status bar picks the slot with the maximum :seq as "freshest".

Example

defmodule MyApp.SlotRenderer do
  @behaviour BB.TUI.Renderer

  @impl true
  def summarize([:demo | _], %{name: name, value: value}) do
    "#{name} = #{value}"
  end

  def summarize(_path, _payload), do: nil

  @impl true
  def observed([:demo | _], %{name: name, value: value} = p) do
    {name, %{label: "#{name}:#{value}"},
     %{freshness: Map.get(p, :freshness, :fresh), seq: Map.get(p, :seq, 0)}}
  end

  def observed(_path, _payload), do: nil
end

Then:

BB.TUI.run(MyApp.Robot,
  subscribe_paths: [[:demo]],
  renderers: %{[:demo] => MyApp.SlotRenderer}
)

Summary

Types

The status-bar display map. bb_tui reads at least :label.

Slot metadata. Carries at least :freshness and a sortable :seq.

A registered slot key — any term the renderer uses to identify a slot.

Callbacks

Returns {slot_key, display, meta} to record/refresh an at-a-glance status-bar slot, or nil to skip. Optional — a renderer that only needs an event-log row can omit it.

Returns a one-line event-log summary for payload on path, or nil to fall back to bb_tui's generic inspect/2 rendering.

Types

display()

@type display() :: %{optional(atom()) => term()}

The status-bar display map. bb_tui reads at least :label.

meta()

@type meta() :: %{freshness: :fresh | :stale, seq: term()}

Slot metadata. Carries at least :freshness and a sortable :seq.

slot_key()

@type slot_key() :: term()

A registered slot key — any term the renderer uses to identify a slot.

Callbacks

observed(path, payload)

(optional)
@callback observed(path :: [atom()], payload :: term()) ::
  {slot_key(), display(), meta()} | nil

Returns {slot_key, display, meta} to record/refresh an at-a-glance status-bar slot, or nil to skip. Optional — a renderer that only needs an event-log row can omit it.

summarize(path, payload)

@callback summarize(path :: [atom()], payload :: term()) :: String.t() | nil

Returns a one-line event-log summary for payload on path, or nil to fall back to bb_tui's generic inspect/2 rendering.