I’ve put together a system for automating music for our reception area. The idea is that it will automatically play music between certain hours. If anyone working at our business wants to they can manually cast whatever music they like, but if that stops, it will revert to a random selection of local music.
Part 1: python shuffle script
#!/usr/bin/env python3
import random, sys, os
nl = ['\n', '\r']
mediafiles = sys.stdin.readlines()
random.shuffle(mediafiles)
chosen = mediafiles[0]
while chosen[-1] in nl:
chosen=chosen[:-1]
print (chosen)
Part 2: MQTT publish random track selection:
(I run this script once a minute with cron)
#!/bin/bash
directory=`ls /var/www/html/media/ | /usr/local/bin/random_mediafile` #Pipes media directories to the shuffle script
filename=`ls /var/www/html/media/"${directory}"/ | /usr/local/bin/random_mediafile` #Pipes media files from the randomly chosen directory to the shuffle script, returns one file
mosquitto_pub -h mosquitto.local -t stat/server/currentsong -m "{\"FILENAME\": \"${filename}\",\"DIRECTORY\": \"${directory}\"}" &
Part 3: sensor configuration
- platform: mqtt
name: 'Current music'
value_template: "{{value_json.FILENAME}}"
json_attributes_topic: "stat/server/currentsong"
state_topic: "stat/server/currentsong"
Part 4: script to play song
chromecast_music_playlist:
alias: "Play a song at random from available songs"
sequence:
- service: media_player.play_media
data_template:
entity_id:
- media_player.music #The chromecast device
media_content_id: "http://LOCAL_MEDIASERVER/media/{{ state_attr('sensor.current_music','DIRECTORY') }}/{{ state_attr('sensor.current_music','FILENAME') }}"
media_content_type: "audio"
Part 5: automations
- id: continue_music
alias: "Continue music if stops"
trigger:
- platform: state
entity_id: media_player.music
to: 'off'
for:
seconds: 4
- platform: state
entity_id: media_player.music
to: 'idle'
for:
seconds: 4
- platform: state
entity_id: input_boolean.reception_music
to: 'on'
condition:
- condition: state
entity_id: input_boolean.reception_music
state: 'on'
- condition: or
conditions:
- condition: state
entity_id: media_player.music
state: 'idle'
- condition: state
entity_id: media_player.music
state: 'off'
- condition: state
entity_id: media_player.music
state: 'paused'
action:
- service: script.chromecast_music_playlist
- id: marantz_on
alias: "Turn on amplifier when chromecast audio in use"
trigger:
- platform: state
entity_id: media_player.music
to: 'playing'
action:
- service: media_player.turn_on
data:
entity_id: media_player.denon_avr
- id: marantz_off
alias: "Turn off amplifier when chromecast audio idle"
trigger:
- platform: state
entity_id: media_player.music
to: 'off'
for:
seconds: 45
- platform: state
entity_id: media_player.music
to: 'idle'
for:
seconds: 45
action:
- service: media_player.turn_off
data:
entity_id: media_player.denon_avr
Now all you need to do is create whatever conditions that control the reception_music input boolean. Whenever that turns on, it will trigger music to start. When turned off, no further tracks will play after the currently playing track. Personally I’ve set up an automation to turn on the boolean when I arrive at my workplace and off when I leave.
One irritation is the long (4 second) wait. This was necessary to enable casting other content. When that time was shorter, attempts to cast something else would fail because the script would take back over. I can probably come up with a way to improve that aspect.