Bear That Codes

The Kitchen Disco

Published on 4 min read

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…

An industrial button with a large green top

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.

A screenshot of the setup of the trigger for a door/window sensor being used as a button

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”)

A screenshot of the setup of the Dropdown Helper in Home Assistant

While here, we also need a boolean to record whether we’re playing a song…

A screenshot of the setup of the Toggle called KitchenDisco.Running used in Home Assistant

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!