So, inspired by another Home Assistant user (and with a lot of inspriation from their scripts - thanks brad at toot.chez.gay on Mastodon for this!) I’ve setup the kitchen disco.
This is basically a set of home automation scripts, controlled by a big industrial green button like this one…
Inside the casing is a cannibalized zigbee door/window sensor - the board has a reed switch on it, which makes it easy to solder some wires to in order to connect to the momentary switch. The original board fits within the cavity under the button, making the whole thing self contained!
Paired to home assistant, it still appears as a door/window switch (so the state is open/closed, rather than on/off, but can still be used to trigger automations when it “closes” (i.e. the button is pressed) - so that’s a good starting point.
The hard part of this process was to create a folder of files, and have home assistant pick a song at random and play it.
This took a few steps…
1: Create a media folder, and upload some MP3 files. This is done in the “Media” page on Home Assistant
Once this is done, add the following to configuration.yaml to allow the folder to be used as a media source for media players controlled by Home Assistant (in my case, I called the folder “kitchen-disco” in the media panel.)
homeassistant:
allowlist_external_dirs:
- /media/kitchen-disco
Next step is to create a DropDown helper (in my case, again called “kitchen_disco”)
While here, we also need a boolean to record whether we’re playing a song…
The input_boolean/dropdown is populated at startup by the following automation - which reads the folder and creates a list of tracks to play in a random order:
alias: kitchendisco.onstartup
description: ""
trigger:
- platform: homeassistant
event: start
condition: []
action:
- service: input_select.set_options
metadata: {}
data:
options: >-
{% set songs = state_attr('sensor.kitchen_disco', 'file_list') |
map('replace', '/media/kitchen-disco/', '') | list %}{% set ns =
namespace(x = songs) %}{% for i in range(ns.x | length - 1, 0, -1) %}{%
set j = range(0, i + 1) | random %}{% if j != i %} {% set ns.x =
ns.x[:j]+[ns.x[i]]+ns.x[j+1:i]+[ns.x[j]]+ns.x[i+1:] %}{% endif %}{%
endfor %}{{ ns.x }}
target:
entity_id: input_select.kitchen_disco
mode: single
Once this was done, the final automations just react to the button (which toggles the input boolean), and react to the changes of state of the input by calling scripts that command the media player in the kitchen to play a track, switch on the “disco lights” and then when the track is over, turn the lights off again.
alias: kitchendisco.inputboolean.on
description: ""
trigger:
- platform: state
entity_id:
- input_boolean.kitchendisco_running
from: "off"
to: "on"
condition: []
action:
- service: script.turn_on
target:
entity_id: script.kitchendisco_button_pressed
data: {}
mode: single
alias: kitchendisco.song_ended
description: ""
trigger:
- platform: state
entity_id:
- media_player.petes_office_2
from: playing
to: paused
- type: not_opened
platform: device
device_id: 7c449f96a26bdbb3e18325e1608d1867
entity_id: 62208c0ea011013a93a22b952f301eac
domain: binary_sensor
condition:
- condition: state
entity_id: input_boolean.kitchendisco_running
state: "on"
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.kitchendisco_running
data: {}
- service: script.turn_on
metadata: {}
data: {}
target:
entity_id: script.kitchendisco_reset
mode: single
This is the main script - plays the next track, sets up the lights (storing the current state of the kitchen lights too)
alias: kitchendisco.button.pressed
sequence:
- service: scene.create
data:
scene_id: kitchencurrentstate
snapshot_entities:
- light.lumi_lumi_switch_l2aeu1_light_3
- light.lumi_lumi_switch_l2aeu1_light_4
- service: input_boolean.turn_on
metadata: {}
data: {}
target:
entity_id: input_boolean.kitchendisco_running
- service: media_player.play_media
metadata: {}
data:
media_content_id: >-
{{ '/media/local/kitchen-disco/' + states('input_select.kitchen_disco')
}}
media_content_type: music
target:
entity_id: media_player.kitchen
- type: turn_on
device_id: fa8b7bc150e6383d022e157baf14c2cc
entity_id: 9cbbe913e0b83341a7c22c3456950c93
domain: switch
- type: turn_off
device_id: b00d8825d3b5ff66b3999289f5f29214
entity_id: b77f72f72e2b291d35a198fe0794065c
domain: light
mode: single
icon: mdi:play
Finally the reset script, which returns the lights to the original state, and moves the dropdown selection to the next track
alias: kitchendisco.reset
sequence:
- service: input_boolean.turn_off
metadata: {}
data: {}
target:
entity_id: input_boolean.kitchendisco_running
- service: media_player.media_stop
metadata: {}
data: {}
target:
entity_id:
- media_player.petes_office_2
- service: input_select.select_next
target:
entity_id: input_select.kitchen_disco
data:
cycle: true
- type: turn_off
device_id: fa8b7bc150e6383d022e157baf14c2cc
entity_id: 9cbbe913e0b83341a7c22c3456950c93
domain: switch
- service: scene.turn_on
metadata: {}
target:
entity_id: scene.kitchencurrentstate
mode: single
Finally it all comes together… push the button, get the disco!