Skip to content

Instantly share code, notes, and snippets.

@Gaff
Last active March 15, 2026 07:39
Show Gist options
  • Select an option

  • Save Gaff/debf6459da0a815b7ee6b3b06a7b9570 to your computer and use it in GitHub Desktop.

Select an option

Save Gaff/debf6459da0a815b7ee6b3b06a7b9570 to your computer and use it in GitHub Desktop.
Aquara Magic Cube - Spotify Helper
blueprint:
name: Aquara Cube - Spotify Blueprint (Links & Gestures)
description: Gestures for Spotify. Faces 1-5 = Playlists, Face 6 = pause. Slide = play/pause. Rotate = next/prev. Shake = shuffle. Supports Spotify sharing URLs.
domain: automation
input:
cube_device:
name: Magic Cube Device
description: Select your Aqara Magic Cube
selector:
device:
integration: zha
manufacturer: LUMI
speaker:
name: Spotify Speaker
selector:
entity:
domain: media_player
# FACE 1
playlist_1_name:
name: Face 1 Label (Optional)
description: A friendly name so you remember what this face plays
default: ""
playlist_1:
name: Face 1 Spotify URL
description: "Paste a standard web link from the 'Share' menu. Example: https://open.spotify.com/playlist/..."
selector:
text:
default: "https://open.spotify.com/playlist/your_shared_link_here"
# FACE 2
playlist_2_name:
name: Face 2 Label (Optional)
default: ""
playlist_2:
name: Face 2 Spotify URI
description: "Direct Spotify URIs also work perfectly. Example: spotify:album:..."
selector:
text:
default: "spotify:album:your_uri_style_link_here"
# FACE 3
playlist_3_name:
name: Face 3 Label (Optional)
default: ""
playlist_3:
name: Face 3 Spotify Link / URI
selector:
text:
default: ""
# FACE 4
playlist_4_name:
name: Face 4 Label (Optional)
default: ""
playlist_4:
name: Face 4 Spotify Link / URI
selector:
text:
default: ""
# FACE 5
playlist_5_name:
name: Face 5 Label (Optional)
default: ""
playlist_5:
name: Face 5 Spotify Link / URI
selector:
text:
default: ""
mode: single
trigger:
- platform: event
event_type: zha_event
event_data:
device_id: !input cube_device
variables:
speaker: !input speaker
command: '{{ trigger.event.data.command | default("") }}'
face: '{{ trigger.event.data.args.activated_face | default(0) | int }}'
playlists:
- !input playlist_1
- !input playlist_2
- !input playlist_3
- !input playlist_4
- !input playlist_5
action:
- choose:
# Face 6 = pause (Supports both 'scene' and 'flip')
- conditions: "{{ command in ['scene', 'flip'] and face == 6 }}"
sequence:
- service: media_player.media_pause
target:
entity_id: '{{ speaker }}'
# Face 1-5 = play playlist
# Also ensures we don't try to play the dummy default text
- conditions: >
{{ command in ['scene', 'flip'] and face >= 1 and face <= 5
and playlists[face-1] != ''
and 'your_' not in playlists[face-1] }}
sequence:
- variables:
raw_url: '{{ playlists[face-1] }}'
# Extract the media type (playlist, album, artist, track) from either the URL or URI
media_type: >
{% if "spotify.com/" in raw_url %}
{{ raw_url.split("spotify.com/")[1].split("/")[0] }}
{% elif "spotify:" in raw_url %}
{{ raw_url.split(":")[1] }}
{% else %}
playlist
{% endif %}
# Convert Spotify URL to proper URI format and strip out tracking queries like ?si=xxxx
media_id: >
{% if "spotify.com/" in raw_url %}
spotify:{{ media_type }}:{{ raw_url.split("spotify.com/")[1].split("/")[1].split("?")[0] }}
{% else %}
{{ raw_url }}
{% endif %}
- service: media_player.play_media
target:
entity_id: '{{ speaker }}'
data:
media_content_type: '{{ media_type }}'
media_content_id: '{{ media_id }}'
# Slide = play/pause toggle
- conditions: "{{ command == 'slide' }}"
sequence:
- service: media_player.media_play_pause
target:
entity_id: '{{ speaker }}'
# Rotate right = next track
- conditions: "{{ command == 'rotate_right' }}"
sequence:
- service: media_player.media_next_track
target:
entity_id: '{{ speaker }}'
# Rotate left = previous track
- conditions: "{{ command == 'rotate_left' }}"
sequence:
- service: media_player.media_previous_track
target:
entity_id: '{{ speaker }}'
# Shake = shuffle (Turns shuffle on)
- conditions: "{{ command == 'shake' }}"
sequence:
- service: media_player.shuffle_set
target:
entity_id: '{{ speaker }}'
data:
shuffle: true
default:
# <reserved for future expansion>
- delay: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment