Last active
May 22, 2022 10:56
-
-
Save lymbada/47c9164f14fe1d58ac5b929da6358e17 to your computer and use it in GitHub Desktop.
Spotify Select Player - a blueprint that will select a spotify account from an (ordered) list, to play music on a specific player (if available)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (c) 2022, Matthew Tilney | |
# All rights reserved. | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are met: | |
# * Redistributions of source code must retain the above copyright notice, this | |
# list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above copyright notice, | |
# this list of conditions and the following disclaimer in the documentation | |
# and/or other materials provided with the distribution. | |
# * Neither the name of the copyright holder nor the names of its | |
# contributors may be used to endorse or promote products derived from | |
# this software without specific prior written permission. | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
blueprint: | |
name: Spotify Select Player | |
description: > | |
Allows for automatic selection of a spotify account to be used with the specified source: | |
a) selects the current Spotify account already playing on the source, | |
b) select an account currently not playing from the (ordered) Spotify Accounts list | |
Once (if) a sutiable play is found, the source will be set on the specific Spotify account, and the URL linked to the input_text field will start playing; | |
(to get the Spotify url for media contect, find a Spotify playlist you like, use the ... -> Share -> copy link to playlist; and past this into your specified input_text | |
Dependencies: HA Spotify Intergration for at least 1 account (but mutiple supported, this is the whole point) | |
Issues: Sources are only avaliable in Home Assistant (viat the Spotify Intergration & Web-API) if: | |
1. The account is signed into the specific Spotify account on the source | |
2. A local App is currently open (and internet accessable) on a device on the same network as the source. | |
- Workaround on RiPi devices (yet to be posted - May2022), run mutiple raspotify docker containers on the same devices, with the same name, each signed in to a different account | |
domain: script | |
input: | |
source_name: | |
name: Source Name | |
description: Name of the source (must be avaliable in the source_list for each spotify player to work on that account) | |
selector: | |
text: | |
media_list: | |
name: Spotify Accounts | |
description: Spotify Accounts list (ordere list, 1st one is checked first) for Spotify which could use for playing music | |
default: {entity_id: []} | |
selector: | |
target: | |
entity: | |
integration: spotify | |
media_content: | |
name: Media Content as Input Text | |
description: The media content url for spotify, can be playlist album, or track fron a previously populated input_text helper | |
selector: | |
entity: | |
domain: input_text | |
test_mode_enabled: | |
name: Test Mode | |
description: Some actions (specificall the source select and play media) are skipped, and output of which entity would be used is written to the log (WARN level) | |
default: false | |
selector: | |
boolean: | |
variables: | |
spotify_accounts: !input 'media_list' | |
output_source: !input 'source_name' | |
media_content: !input 'media_content' | |
test_mode: !input 'test_mode_enabled' | |
alias: Spotify Select Player (blueprint) | |
sequence: | |
- service: homeassistant.update_entity | |
data: {} | |
target: | |
entity_id: > | |
{% if spotify_accounts is not defined %}{% set spotify_accounts = namespace(entity_id = integration_entities("spotify") ) %}{% endif %} {% set | |
output_source = 'spotify-player'%} {%- set spotifies = namespace(entities=[]) | |
-%} {% for entity in states.media_player %} | |
{% if entity.entity_id in spotify_accounts.entity_id %} | |
{%- set spotifies.entities = spotifies.entities + [entity] -%} | |
{% set entities = spotifies.entities %} | |
{% endif %} | |
{% endfor %} {{ spotifies.entities | map(attribute='entity_id') | list | |
}} | |
- delay: | |
hours: 0 | |
minutes: 0 | |
seconds: 1 | |
milliseconds: 0 | |
- if: | |
- condition: not | |
conditions: | |
- condition: template | |
value_template: !input 'test_mode_enabled' | |
then: | |
- service: media_player.select_source | |
target: | |
entity_id: > | |
{# Determin which media play can be used for the current sctip#} {# | |
Convert input entity_id list into full spotify entites in the HA | |
setup #} {% set spotifies = namespace(entities=[]) -%} {% set | |
potential_players = namespace(entities=[])%} {% set spotify_list = | |
[] -%} {% for player in spotify_accounts.entity_id %} {% if player | |
in integration_entities("spotify")%} {# I don't like having to use a | |
2nd loop, when a way of getting full entity from entity_id as a | |
command is possiable, this bit will no longer be rquired #} {% for | |
player_entity in states.media_player %}{% if player_entity.entity_id | |
== player %} {% set spotifies.entities = spotifies.entities + | |
[player_entity] -%} {% set entities = spotifies.entities %} {% | |
endif %}{% endfor %}{% endif %}{% endfor %} {# Perform the specific | |
selections, 1st if the device is already playing on the source, 2nd | |
and spotify account not playing that also has acccess to the source | |
#} {% for player in (spotifies.entities | | |
selectattr('state','ne','idle') | selectattr('attributes.source', | |
'search', output_source) | list )%} {%- set | |
potential_players.entities = potential_players.entities + [player] | |
-%} {% endfor %} {% for player in (spotifies.entities | | |
selectattr('state','ne','playing') | | |
selectattr('attributes.source_list','search',output_source) | list | |
)%} {%- set potential_players.entities = potential_players.entities | |
+ [player] -%} {% endfor %} {# Return the 1st spotify entity_id from | |
the found list#} {{ (potential_players.entities | | |
map(attribute='entity_id') | list)[0] }} | |
data: | |
source: !input 'source_name' | |
- delay: | |
hours: 0 | |
minutes: 0 | |
seconds: 2 | |
milliseconds: 500 | |
- service: media_player.play_media | |
data: | |
media_content_id: > | |
{{ states(media_content) }} | |
media_content_type: playlist | |
target: | |
entity_id: > | |
{# Determin which media play can be used for the current sctip#} {# | |
Convert input entity_id list into full spotify entites in the HA | |
setup #} {% set spotifies = namespace(entities=[]) -%} {% set | |
potential_players = namespace(entities=[])%} {% set spotify_list = | |
[] -%} {% for player in spotify_accounts.entity_id %} {% if player | |
in integration_entities("spotify")%} {# I don't like having to use a | |
2nd loop, when a way of getting full entity from entity_id as a | |
command is possiable, this bit will no longer be rquired #} {% for | |
player_entity in states.media_player %}{% if player_entity.entity_id | |
== player %} {% set spotifies.entities = spotifies.entities + | |
[player_entity] -%} {% set entities = spotifies.entities %} {% | |
endif %}{% endfor %}{% endif %}{% endfor %} {# Perform the specific | |
selections, 1st if the device is already playing on the source, 2nd | |
and spotify account not playing that also has acccess to the source | |
#} {% for player in (spotifies.entities | | |
selectattr('state','ne','idle') | selectattr('attributes.source', | |
'search', output_source) | list )%} {%- set | |
potential_players.entities = potential_players.entities + [player] | |
-%} {% endfor %} {% for player in (spotifies.entities | | |
selectattr('state','ne','playing') | | |
selectattr('attributes.source_list','search',output_source) | list | |
)%} {%- set potential_players.entities = potential_players.entities | |
+ [player] -%} {% endfor %} {# Return the 1st spotify entity_id from | |
the found list#} {{ (potential_players.entities | | |
map(attribute='entity_id') | list)[0] }} | |
else: | |
- service: system_log.write | |
data: | |
level: warning | |
message: > | |
{# Determin which media play can be used for the current sctip#} {# | |
Convert input entity_id list into full spotify entites in the HA | |
setup #} {% set spotifies = namespace(entities=[]) -%} {% set | |
potential_players = namespace(entities=[])%} {% set spotify_list = | |
[] -%} {% for player in spotify_accounts.entity_id %} {% if player | |
in integration_entities("spotify")%} {# I don't like having to use a | |
2nd loop, when a way of getting full entity from entity_id as a | |
command is possiable, this bit will no longer be rquired #} {% for | |
player_entity in states.media_player %}{% if player_entity.entity_id | |
== player %} {% set spotifies.entities = spotifies.entities + | |
[player_entity] -%} {% set entities = spotifies.entities %} {% | |
endif %}{% endfor %}{% endif %}{% endfor %} {# Perform the specific | |
selections, 1st if the device is already playing on the source, 2nd | |
and spotify account not playing that also has acccess to the source | |
#} {% for player in (spotifies.entities | | |
selectattr('state','ne','idle') | selectattr('attributes.source', | |
'search', output_source) | list )%} {%- set | |
potential_players.entities = potential_players.entities + [player] | |
-%} {% endfor %} {% for player in (spotifies.entities | | |
selectattr('state','ne','playing') | | |
selectattr('attributes.source_list','search',output_source) | list | |
)%} {%- set potential_players.entities = potential_players.entities | |
+ [player] -%} {% endfor %} {# Write out to log file (for enabled | |
mode) #} List of spotify accounts (1st will be selected) | |
{{potential_players.entities | map(attribute='entity_id') | list }}; | |
with the source set as: {{ output_source }}; the content will be {{states(media_content)}}- Testmode: {{ test_mode }} | |
logger: scripts.log | |
mode: single |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment