Skip to content

Latest commit

 

History

History
419 lines (311 loc) · 21.7 KB

File metadata and controls

419 lines (311 loc) · 21.7 KB

Usage & Services

Day-to-day use of the satellite plus every service/action it exposes.

Contents

Starting the Satellite

Once you assign a satellite entity in the sidebar panel, the engine starts automatically and begins listening for wake words. If the browser blocks auto-start due to restrictions, a floating microphone button will appear - tap it to start.

If Auto start is disabled in the panel settings, the engine won't start on page load. Use the Start button in the sidebar panel to activate it manually.

Voice Interaction

Once running, the satellite continuously listens for your configured wake word. When detected:

  1. A wake chime plays (if enabled) and the activity bar appears
  2. Speak your command - the engine streams audio to your STT engine and displays the transcription in real time
  3. The assistant processes your intent and the bar animates while thinking
  4. The TTS response plays and the response text appears on screen
  5. The bar fades and the satellite returns to wake word listening

If the assistant asks a follow-up question or you want to continue the conversation, the engine automatically re-enters listening mode without requiring the wake word again, allowing a natural back-and-forth exchange. This requires a conversation agent that supports multi-turn conversations, such as OpenAI, Google Generative AI, Anthropic, or Ollama. The built-in Home Assistant conversation agent does not support follow-up conversations.

Visual States

The activity bar (styled by the selected skin) indicates the current pipeline state:

State Activity Bar
Listening Hidden (waiting for wake word)
Wake Word Detected Visible, slow animation
Processing Visible, fast animation
Speaking Visible, medium animation

When Reactive activity bar is enabled, the bar also responds to real-time mic input and audio output levels.

Timers

Voice-activated timers work out of the box: "Set a 5 minute timer", "Set a pizza timer for 10 minutes", "Cancel the timer". Pills appear on the overlay with a live countdown, an alert chime fires on completion, and double-tap dismisses. The sidebar panel can also enable a configurable spoken phrase that repeats after every two alert chimes, with only a short pause before the next chime pair.

Timers can also be started from automations via the voice_satellite.start_timer action, and the on-screen pill / alert label can be hidden via the side panel without changing how timers run.

See the Timers reference for the full surface: voice sentences, action schema, automation examples, side-panel options, attributes, and multi-timer behavior.

Announcements

Push TTS announcements to specific devices from automations:

action: assist_satellite.announce
target:
  entity_id: assist_satellite.living_room_tablet
data:
  message: "Dinner is ready!"

Announcements include a pre-announcement chime (ding-dong), play the TTS message, and show the text on screen. If a voice interaction is in progress, the announcement queues and plays after the conversation ends. The announcement blocks until the browser confirms playback is complete (or a 120-second timeout expires), so you can chain actions that depend on the user hearing the message.

The display duration is configurable in the integration's device settings.

Start Conversation

Automations can proactively speak a prompt and listen for the user's response:

action: assist_satellite.start_conversation
target:
  entity_id: assist_satellite.living_room_tablet
data:
  start_message: "The garage door has been open for 30 minutes. Should I close it?"
  extra_system_prompt: "The user was asked about the garage door. If they confirm, call the close_cover service on cover.garage_door."

After the announcement plays, the engine automatically enters listening mode (skipping wake word detection) so the user can respond immediately. The response is processed through the configured conversation agent as a normal voice interaction.

Ask Question

Automations can ask a question, capture the user's voice response, and match it against predefined answers. Requires Home Assistant 2025.7 or later (the assist_satellite.ask_question action was added to core in that release; on older versions the rest of the integration works but this action is unavailable):

action: assist_satellite.ask_question
target:
  entity_id: assist_satellite.living_room_tablet
data:
  question: "The front door has been unlocked for 10 minutes. Should I lock it?"
  answers:
    - id: positive
      sentences:
        - "yes [please]"
        - "[go ahead and] lock it [please]"
        - "sure"
    - id: negative
      sentences:
        - "no [thanks]"
        - "leave it [unlocked]"
        - "don't lock it"
response_variable: answer

After the question plays, a wake chime signals the user to speak. The engine enters STT-only mode to capture the response, then matches it against the provided sentence templates using hassil. The result is returned to the automation via response_variable:

Field Type Description
id string | null Matched answer ID (e.g., "positive"), or null if no match
sentence string Raw transcribed text from STT
slots dict Captured wildcard values from {placeholder} syntax

Sentence templates use hassil syntax: [optional words] and {wildcard} placeholders. For example, "play {genre} music" captures the genre value in answer.slots.genre.

The engine provides audio and visual feedback: a done chime on successful match, or an error chime with a flashing red gradient bar when the response doesn't match any answer.

Voice Satellite Wake Action

Trigger the satellite as if a wake word were detected. Skips wake-word listening and goes directly to STT. Works regardless of the configured wake-word detection mode (On Device vsWakeWord, On Device microWakeWord, On Device openWakeWord, Home Assistant, or Disabled), and is the primary way to drive interactions in Disabled mode.

action: voice_satellite.wake
target:
  entity_id: assist_satellite.living_room_tablet

When fired, the wake chime plays and the mic begins capturing speech for STT. The rest of the pipeline (intent -> TTS -> optional continue-conversation) runs normally. Multi-turn follow-ups are preserved - once the assistant ends the turn without a continue, the mic is released.

The optional wake_word_slot field routes the turn as if that wake-word slot had been detected, so the slot's configured pipeline handles STT, the conversation agent, and TTS. This lets buttons and automations reach Pipeline 2 the same way saying Wake word 2 would. Omitting it keeps the existing behavior (Pipeline 1). Follow-up turns stay on the selected slot's pipeline.

action: voice_satellite.wake
target:
  entity_id: assist_satellite.living_room_tablet
data:
  wake_word_slot: 2

Common uses:

  • A dashboard button that says "Talk to Assist" - wire its tap_action to call this service
  • An automation that activates the satellite when motion or a doorbell triggers
  • Older devices (e.g. Android 7-9) where always-on wake-word detection isn't viable

Note: The first manual wake on a fresh page load may require a prior user gesture in the tab to satisfy the browser's autoplay/permission policy. After that, the action works freely from any source.

Voice Satellite Show Action

Run a prompt through the satellite's Assist pipeline as if the user had spoken it, then pin the response (with any tool-call rich media) on screen until dismissed. Designed for scheduled tasks like a morning briefing, a weather summary on motion, or a calendar peek when you walk into a room.

action: voice_satellite.show
target:
  entity_id: assist_satellite.kitchen_tablet
data:
  prompt: "What's the weather forecast for today?"

When fired, the wake chime plays, the prompt runs through the satellite's pipeline (skipping the STT stage), and the LLM response appears in the standard assistant bubble. Tool-call rich media (weather, image, video, stocks, etc.) renders the same way it does for a wake-word interaction. The bubble stays on screen indefinitely until the user dismisses it (stop word, double-tap, or Escape).

Fields

Field Type Default Description
prompt string (required) Text sent to the Assist pipeline, as if the user had spoken it.
silent boolean true When true, only display the response. When false, also speak it through the pipeline's TTS engine.
pipeline int or string 1 Which pipeline runs the prompt. Pass 1 or 2 to use the matching wake-word slot's pipeline, or pass an exact pipeline name to override.
duration int (seconds) 0 Auto-dismiss after N seconds. 0 keeps the bubble on screen until manual dismissal.

Examples

All parameters set explicitly:

action: voice_satellite.show
target:
  entity_id: assist_satellite.kitchen_tablet
data:
  prompt: "Show me the weather forecast for the day"
  silent: false
  pipeline: 1
  duration: 60

Daily 8 AM weather forecast automation:

alias: Morning weather forecast
trigger:
  - platform: time
    at: "08:00:00"
action:
  - action: voice_satellite.show
    target:
      entity_id: assist_satellite.bedroom_tablet
    data:
      prompt: "Show me the weather forecast for the day"

Dismissal

While a show bubble is on screen the activity bar is pinned to a calm "listening" gradient (no mic-driven reactivity). Three ways to dismiss:

  • Stop word - say the engine-specific stop keyword ("stop" on microWakeWord and openWakeWord, "ok stop" on vsWakeWord). Requires Stop word interruption enabled on the device. See Stop Word Interruption
  • Double-tap anywhere on the screen, or press Escape
  • Duration timer - if duration > 0, the bubble auto-dismisses after that many seconds

After dismissal the satellite plays a "done" chime, resumes any media that was paused, and goes back to wake-word listening.

Behavior notes

  • Requires a tool-capable conversation agent for rich media to render. With the built-in Home Assistant agent the response is plain text only.
  • If a voice interaction or another notification (announce / start_conversation / ask_question) is in progress when the show fires, it queues and plays after the current turn finishes.
  • If multiple shows arrive while the previous one is still on screen, the new one replaces the old.
  • If the browser tab is hidden when the show fires, it's queued and runs the moment the tab becomes visible.
  • Pipeline errors (LLM unreachable, intent failure, etc.) dismiss the show automatically and surface through the standard error toast.

Screensaver Control from Automations

Two controls cover the screensaver from automations:

  • The Screensaver switch entity on the satellite device turns the screensaver on or off.
  • The voice_satellite.set_screensaver action changes the screensaver type.

Screensaver Switch

Each satellite exposes a switch entity named Screensaver that enables or disables the built-in screensaver, mirroring the "Enable Voice Satellite screensaver" toggle in the side panel. Turning it off while the screensaver is on screen dismisses it immediately; turning it on arms the idle timer. Because it is a regular Home Assistant switch, its state persists across restarts, applies when a disconnected browser reconnects, and can be used in conditions.

Disable the screensaver while somebody is home, enable it otherwise:

alias: Screensaver only when away
triggers:
  - trigger: state
    entity_id: binary_sensor.kitchen_occupancy
actions:
  - action: >
      switch.turn_{{ 'off' if is_state('binary_sensor.kitchen_occupancy', 'on') else 'on' }}
    target:
      entity_id: switch.kitchen_tablet_screensaver

Voice Satellite Set Screensaver Action

Change the satellite's screensaver type live from an automation. Useful for time-based scheduling such as a black overlay overnight to keep an always-on tablet cool, and a media or website screensaver during the day.

action: voice_satellite.set_screensaver
target:
  entity_id: assist_satellite.kitchen_tablet
data:
  type: black

When fired, the new type is pushed to every browser subscribed to that satellite, persisted to the selected satellite's panel profile, and the screensaver re-renders immediately if it was already on screen. The media file/folder, website URL, idle timeout, brightness percentage, and other screensaver settings continue to come from the side panel.

Fields

Field Type Default Description
type string (required) One of black, media, website, or clock. black is a solid dark overlay (combine with a low brightness percentage in the panel for the strongest thermal savings). media uses the image/video/folder selected in the panel (cameras stream over WebRTC when available). website embeds the URL configured in the panel. clock shows a large digital time and date.

Examples

Black overlay at 11 PM, media kiosk back at 7 AM:

alias: Night-time screensaver
triggers:
  - trigger: time
    at: "23:00:00"
  - trigger: time
    at: "07:00:00"
actions:
  - action: voice_satellite.set_screensaver
    target:
      entity_id: assist_satellite.kitchen_tablet
    data:
      type: "{{ 'black' if now().hour >= 23 else 'media' }}"

Switch a wall tablet to a dashboard website during dinner, back to a photo slideshow afterwards:

alias: Dinner-time recipe screen
triggers:
  - trigger: state
    entity_id: input_boolean.dinner_time
actions:
  - action: voice_satellite.set_screensaver
    target:
      entity_id: assist_satellite.kitchen_tablet
    data:
      type: "{{ 'website' if is_state('input_boolean.dinner_time', 'on') else 'media' }}"

Behavior notes

  • The change applies to every browser currently connected to the targeted satellite. For the typical one-tablet-per-entity setup that is exactly the device you targeted.
  • If no browser is connected when the action fires (tablet off, app closed), nothing changes on screen at that moment, but the new type is still persisted to the satellite's panel profile on the integration side. The browser applies it the next time the page loads and hydrates its settings from the server.
  • If the side panel happens to be open at the moment the action fires, its Screensaver Type dropdown will not live-update. The next time the panel opens it reads the new value from local storage and reflects it correctly.
  • The action only changes the type. To turn the screensaver on or off, use the satellite's Screensaver switch entity (see Screensaver Switch). For an "always on but dark" tablet overnight, pair type: black with a low Screen brightness while active percentage in the panel (0% drives the kiosk app backlight fully off - Kiosk Satellite, Fully Kiosk, or Kiosker Pro).

Media Player

Each satellite automatically exposes a media_player entity in Home Assistant, registered with device_class: tv so it can be targeted for both audio and video. The entity:

  • Controls volume for all satellite audio (chimes, TTS, announcements) via the HA volume slider
  • Reflects playback state - shows "Playing" whenever any sound is active on the satellite
  • Supports tts.speak - target the satellite as a TTS device in automations
  • Supports media_player.play_media for audio, local video files, and live camera streams
  • Supports browsing the HA media library, including the Cameras source

Routing TTS to a different speaker. This section covers the satellite's own media_player entity (the tablet itself). To route the assistant's spoken response to a different speaker, see TTS Output.

Audio

# Play audio on the satellite
action: media_player.play_media
target:
  entity_id: media_player.kitchen_tablet_media_player
data:
  media_content_id: media-source://media_source/local/doorbell.mp3
  media_content_type: music

# Use the satellite as a TTS target
action: tts.speak
target:
  entity_id: tts.piper
data:
  media_player_entity_id: media_player.kitchen_tablet_media_player
  message: "The laundry is done!"

Video and camera streams

When a video file or camera stream is sent to the satellite, the browser renders a full-screen overlay over the entire UI:

  • Local video files (.mp4, .webm, etc.) play in a <video> element with the browser's native playback controls (play/pause/seek/volume)
  • Cameras with a WebRTC provider (any camera with a stream source on a modern HA install, courtesy of HA's built-in go2rtc) play over WebRTC with sub-second latency. The stream is negotiated over the satellite's authenticated websocket connection (camera/webrtc/offer), so no extra configuration, CORS setup, or exposed go2rtc URL is needed
  • Cameras without WebRTC but with the Stream integration fall back automatically to HLS (application/vnd.apple.mpegurl). Playback uses hls.js, which is lazy-loaded on first use, so audio-only setups don't pay the bundle cost. Safari falls through to native HLS automatically
  • Cameras without Stream support (snapshot or MJPEG) are served via /api/camera_proxy_stream/<entity> and rendered in an <img> element. No native controls (browsers don't provide any for multipart/x-mixed-replace); use double-tap or the stop keyword to dismiss
# Play a video file
action: media_player.play_media
target:
  entity_id: media_player.kitchen_tablet_media_player
data:
  media_content_id: media-source://media_source/local/recipe.mp4
  media_content_type: video/mp4

# Show a live camera feed (WebRTC when available, HLS/MJPEG fallback)
action: media_player.play_media
target:
  entity_id: media_player.kitchen_tablet_media_player
data:
  media_content_id: media-source://camera/camera.front_door
  media_content_type: application/vnd.apple.mpegurl

A bare camera entity id also works as media_content_id (e.g. camera.front_door with any media_content_type), which is convenient when templating automations.

Dismissal:

  • Double-tap anywhere on the overlay (outside the video controls)
  • Stop keyword ("stop" on MWW/OWW, "ok stop" on vsWakeWord) when stop-word interruption is enabled on the satellite
  • media_player.media_stop action from automations

Wake-word interaction:

While a video or camera stream is playing, saying the satellite's wake word hides the overlay and runs the voice flow as usual. When the flow finishes, the overlay reappears and playback resumes. For HLS streams the player automatically jumps to the live edge on resume, so you don't watch buffered footage from before the interruption.

HLS live latency (fallback path only):

Cameras playing over WebRTC have sub-second latency out of the box and none of this applies. For cameras that fall back to HLS: HLS is inherently buffered. With Home Assistant's default stream configuration, expect a 2 to 4 second lag from real time. The integration tunes hls.js (liveSyncDuration, liveMaxLatencyDuration, backBufferLength, maxLiveSyncPlaybackRate) to stay close to the live edge and to catch up gracefully if the stream falls behind, but the floor is set server-side by HA's segment duration.

For sub-second latency, enable Low-Latency HLS in your HA configuration.yaml and restart Home Assistant:

stream:
  ll_hls: true
  part_duration: 0.5

The integration already sends lowLatencyMode: true to hls.js, so once HA serves LL-HLS parts the player picks them up automatically with no further configuration on the satellite.

The entity supports play, pause, resume, stop, seek, volume set, and volume mute (volume is a no-op for MJPEG streams, which carry no audio). All commands work from the HA UI, automations, and media_player.* services.

Position and media info:

For seekable media (local files, podcasts, most Music Assistant tracks) the entity reports media_position and media_duration, so the standard media control card shows a progress bar you can drag. Live HLS, WebRTC and MJPEG streams have no fixed length and report neither.

The entity also fills media_title and album art when it knows them. Items picked in Home Assistant's media browser keep the title and thumbnail shown there (radio stations bring their logo along, for example). Local media library files fall back to the file name. Automations can pass their own details through the extra field of media_player.play_media, using the same keys Google Cast accepts:

action: media_player.play_media
target:
  entity_id: media_player.kitchen_tablet
data:
  media_content_id: https://example.com/stream.mp3
  media_content_type: music
  extra:
    title: Morning Mix
    artist: Some Artist
    thumb: https://example.com/cover.jpg

Skip, previous, shuffle and repeat are not part of this entity because it plays a single item at a time and has no queue. When Music Assistant is the source, use the Music Assistant player entity for the satellite: it owns the queue and exposes those controls along with full track metadata.