Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

141 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

odio

odio-ha

Native Home Assistant integration for odio, every node exposed as HA entities.

Release Home    
  Assistant Silver integration License CI GitHub Sponsors

Add to HACS Media players Real-time SSE Zeroconf discovery

Part of the odio project — full documentation.

Python Home Assistant HACS GitHub Actions

Odio Remote - Home Assistant Integration

Control your Linux multimedia setup remotely from Home Assistant.

This integration connects to a Linux machine running the go-odio-api server and turns it into a discoverable and controllable media hub. Backends (audio, power, services, etc.) are configured and exposed directly on the server side. HA discovers them automatically via the API.

Features

Core

  • Zeroconf (mDNS) auto-discovery
  • One single “Odio Remote (hostname)” device grouping all entities
  • Backends detected automatically from server config — no toggles in HA
  • Always-visible connectivity sensor (diagnostic)
  • MAC address resolved via Device Tracker

Real-time updates (SSE)

All state is pushed by the server via Server-Sent Events — no polling after initial fetch.

  • Coordinators refresh once at startup, then stay in sync via SSE
  • Automatic reconnection with exponential backoff (1s → 5min)
  • Configurable server-side keepalive interval (default 30s, range 10–120s)

Audio (PulseAudio / PipeWire backend)

  • Main receiver media_player with global volume/mute
  • Audio output selection via source list on the receiver. Unlike traditional media players, Odio has no exclusive source concept: all sources can be active simultaneously. The source list is used to select the default audio output, not to switch between inputs.
  • Default output sensor with full output attributes
  • Remote audio client entities (PipeWire tunnels from other machines)
  • No local clients for now due to name collision risks

Services (systemd backend)

  • media_player entity per detected user-scope systemd service
  • Start/stop switch per service
  • Optional mapping to an existing HA media player → inherits full playback controls & metadata

MPRIS (media player backend)

  • media_player entity per active D-Bus MPRIS player (Spotify, Firefox, Chromium, mpd, etc.)
  • Full transport controls: play/pause/stop/next/previous/seek (when the player supports them)
  • Volume control, shuffle, and repeat mode
  • Rich metadata: title, artist, album, album art (remote URLs only)
  • Live position tracking via SSE
  • Players appear/disappear dynamically as they start and stop
  • Optional mapping to an existing HA media player for fallback controls

Bluetooth

Control your Bluetooth adapter directly from Home Assistant:

  • Power switch — turn the adapter on or off
  • Pairing mode button — make the device discoverable for 60 seconds (inbound: host acts as a speaker)
  • Pairing active sensor — know when pairing is in progress (diagnostic)
  • Connected device sensor — name of the currently connected device

Connect to external Bluetooth speakers / headphones (outbound):

  • Scan switch — start/stop discovery of nearby Bluetooth audio devices
  • Pair device select — lists devices found during a scan that aren't paired yet; pick one to connect & pair it. Available only while pairable devices are in range.
  • One switch per known device (paired/bonded) — turn on to connect, off to disconnect. Created dynamically; a device that leaves the known list goes unavailable instead of disappearing.
  • Once connected, the device becomes a PulseAudio/PipeWire sink — so it shows up in the receiver's output source list and is selectable as the default output, no extra setup.

Power (power backend)

  • Shutdown and reboot buttons

Upgrade (upgrade backend)

Exposes a server-configured upgrade as a native HA update entity, presented as Firmware. What gets detected and upgraded (version source, detection schedule, upgrade command) is entirely configured on the go-odio-api server — HA just reflects it.

  • Installed/latest version tracking, "update available" when the server-side detector reports one
  • Install button to start the upgrade (POST /upgrade/start), shown only when the server allows it
  • Live progress percentage while a run is in flight
  • Detection is fully server-driven (systemd timer + fsnotify push over SSE) — HA never polls or re-checks

Mapping to existing media players

You can map Odio entities (services or remote clients) to any existing HA media_player entity via the configuration or reconfiguration flow.

Examples:

  • Map a service like mpd.service to media_player.music_player_daemon
  • Map an audio client like a PipeWire tunnel to media_player.kodi_htpc

When mapped, the Odio entity combines:

  • Start/stop control via systemd (for services only)
  • Independent volume and mute control via PulseAudio/PipeWire (global or per-client)
  • All native features of the mapped entity: play/pause/stop/next/previous/seek/shuffle/repeat/select_source/media_title/media_artist/media_album_name/entity_picture (album art)/media_position/media_duration/shuffle/repeat/source/source_list/etc.

Without mapping, the Odio entity only provides basic volume/mute and playback state (playing/idle).

This way, Odio augments your existing players with Linux-level audio control and service management, without replacing their core playback features.

Screenshots

With poweroff and reboot enabled

With poweroff and reboot enabled

Without poweroff and reboot enabled. Default on go-odio-api

Without poweroff and reboot enabled

With MPD mapped

With MPD mapped

Installation

Via HACS (recommended)

Add odio-ha integration via HACS

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

Manual installation

  1. Download the latest release
  2. Copy custom_components/odio_remote into your config/custom_components/ folder
  3. Restart Home Assistant

Setup

Add your device via the Integration menu

Open your Home Assistant instance and start setting up a new integration.

  1. Go to Settings → Devices & Services → Add Integration
  2. Search for Odio Remote
  3. It should auto-discover via Zeroconf (shows your Linux hostname)
    • If not, enter the API URL manually (http://ip:port)
  4. No backend toggles in HA — everything depends on what your go-odio-api server exposes (see its config)

Required: go-odio-api running on your Linux machine. Check its README for setup, endpoints, and how to enable specific backends.

Entities Created

All grouped under one device: ”Odio Remote (hostname)”.

Always present

Entity Description
media_player.odio_remote_[hostname] Main hub — state: playing / idle / unavailable. Global volume/mute and audio output selection when audio backend enabled.
binary_sensor.odio_remote_[hostname]_connection_status SSE stream connected (diagnostic)

Audio backend (PulseAudio / PipeWire)

Entity Description
sensor.odio_remote_[hostname]_default_output Current default audio output with full attributes (name, volume, muted, state, driver, etc.)
media_player.odio_remote_[hostname]_[client] Remote audio client (PulseAudio/PipeWire tunnel) — volume/mute, optional mapping

Services backend (systemd)

Entity Description
media_player.odio_remote_[hostname]_[service] One per user-scope service — start/stop, volume/mute, optional mapping for full playback
switch.odio_remote_[hostname]_[service] Direct start/stop toggle per service

MPRIS backend

Entity Description
media_player.odio_remote_[hostname]_[player] One per MPRIS player (e.g. Spotify, Firefox) — transport controls, volume, metadata, position tracking

Bluetooth backend

Entity Description
switch.odio_remote_[hostname]_bluetooth_power Power the Bluetooth adapter on/off
switch.odio_remote_[hostname]_bluetooth_scan Start/stop discovery of nearby Bluetooth audio devices
select.odio_remote_[hostname]_bluetooth_pair Pair a newly discovered (unpaired) device by selecting it
switch.odio_remote_[hostname]_bluetooth_device_[address] One per paired/bonded device — connect/disconnect (dynamic)
button.odio_remote_[hostname]_bluetooth_pairing Trigger pairing mode (60s server-side timeout)
binary_sensor.odio_remote_[hostname]_bluetooth_pairing_active Pairing mode currently active (diagnostic)
sensor.odio_remote_[hostname]_bluetooth_connected_device Name of the connected device, empty when none

Power backend

Entity Description
button.odio_remote_[hostname]_power_off Shut down the machine
button.odio_remote_[hostname]_reboot Reboot the machine

Upgrade backend

Entity Description
update.odio_remote_[hostname]_firmware Firmware update — installed/latest version, install button (when allowed), live progress

Roadmap

  • More Sensors: Tell me what you need for your setup !
  • Improved error reporting & options flow

Note on backends: Enabling/disabling features (audio, power, services…) is handled exclusively on the go-odio-api server for security reasons (exposing config via API would introduce risks). HA only reflects what the server makes available.

Troubleshooting

Enable debug logs:

configuration.yaml

logger:
  default: warning
  logs:
    custom_components.odio_remote: debug
    custom_components.odio_remote.config_flow: debug
    custom_components.odio_remote.media_player: debug

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

For issues and questions: GitHub repository

License

This project is licensed under the MIT License - see the LICENSE file for details.