title: Random Audiobook on MPD order: 10 --- I want the Zigbee light switch attached directly to the headboard of my bed to play a random Sherlock Holmes or Three Investigators episode when pressed and held. To do this, I first need to write a Python script that connects to my [MPD](https://de.wikipedia.org/wiki/Music_Player_Daemon) and retrieves a list of all possible audiobooks, then selects one at random and plays it. The script then needs to be made available on the Pi running Home Assistant and linked to the button. ## Setup Homeassistant I run Homeassistant inside a Docker container. Therefor i need to mount the folder with the python script inside the container. I use the /opt directly in this setup ``` services: homeassistant: image: "ghcr.io/home-assistant/home-assistant:stable" volumes: - /opt/:/opt/root ... ``` after that i could make the script visible to homeassistant by adding the following content to my `configuration.yaml`: ``` shell_command: hoerbuch: python3 /opt/root/randomhoerbuch ``` Than i used the Homeassistant GUI to create an automation which run the script on the hold action of the button: ``` alias: Button Bed Long description: "" trigger: - platform: device domain: mqtt device_id: cdb815a53346bc4bca446b097a2da234 type: action subtype: hold discovery_id: 0x00158d00027d83ba action_hold condition: [] action: - service: shell_command.hoerbuch data: {} mode: single ``` ## Python code ```pthon #!/bin/python3 import random from mpd import MPDClient # Konfigurierbare Einstellungen MPD_HOST = "192.168.1.101" MPD_PORT = 6600 MPD_PASSWORD = None # oder z.B. "meinPasswort" ALBUM_ARTISTS = ["Sherlock Holms - Aus den Tagebüchern"] # Beispielkünstler def connect_to_mpd(): client = MPDClient() client.timeout = 10 client.idletimeout = None client.connect(MPD_HOST, MPD_PORT) if MPD_PASSWORD: client.password(MPD_PASSWORD) return client def get_albums_by_artist(client, artist): albums = client.list("album", "albumartist", artist) return [album for album in albums if album] def get_songs_from_album(client, artist, album): # Versuche zuerst mit albumartist songs = client.find("albumartist", artist, "album", album) if not songs: # Fallback auf artist, falls albumartist nicht funktioniert songs = client.find("artist", artist, "album", album) print(f"Keine Songs gefunden für:\nArtist: {artist}\nAlbum: {album}") return songs def main(): client = connect_to_mpd() # Alle Alben sammeln artist_album_map = {} for artist in ALBUM_ARTISTS: albums = get_albums_by_artist(client, artist) if albums: artist_album_map[artist] = albums # Zufällig Künstler und Album wählen if not artist_album_map: print("Keine Alben gefunden.") return artist = random.choice(list(artist_album_map.keys())) album_entry = random.choice(artist_album_map[artist]) album = album_entry["album"] if isinstance(album_entry, dict) else album_entry print(f"Spiele zufälliges Album:\nKünstler: {artist}\nAlbum: {album}") # Songs holen und abspielen songs = get_songs_from_album(client, artist, album) client.clear() for song in songs: client.add(song["file"]) client.play() client.close() client.disconnect() if __name__ == "__main__": main() ```