How I Turned My House into Disney's Haunted Mansion using Home Assistant
If you haven’t guess from the topic of this article we are Disney fans in this house. I mean Annual Passholder Card Carrying Disney fans. So after getting Home Assistant setup to automate the house I decided I could use the platform to do a little Disney Imagineering.
Now I didn’t literally recreate the haunted mansion in my house. I’ve seen videos of people that have and well, I don’t need to build a ride to enjoy the experience. But I did take the preshow audio, and add some simple light effects via some Sengled Bulbs. I don’t remember where I got the audio of the ride, but I already had an mp3 version of the full ride. Again, Disney Fans here.
I simply cut out the mp3 down to what I needed and then it was time to get it into Home Assistant.
Now in my Youtube Video walk through of this I was running Hassbian. Shortly after that I made the switch Hassio which required some changes. With Hassbian I could easily use the audio jack on the Pi and VLC to play the audio. This enabled me time exactly when the light effects should happen.
Unfortunately I haven’t figured out a reliable way to play an mp3 via the Hassio docker container using VLC. So I’m using a Chromecast into a receiver that handles the audio for the house, which currently is just a pair of speakers on wireless bridge. I plan to go through that entire audio setup in a future article covering my audio notifications.
The other issue is using the chromecast I haven’t figured out how to get a lock mp3 to play via the media_player.media_play
service. Luckily I have a Ubuntu server that handles some of my non-critical processes. The idea was to offload non-critical stuff to another server to free up my Home Assistant host to focus on critical home automation tasks like security. So just fired up a web server, dropped my mp3s on there, and viola! I now have a stream source that media_player.media_play
service likes.
Once I had the the audio in place it was time automate this thing.
Everything I am going to cover can be found in my haunted_mansion_show.yaml in my packages directory.
If you don’t use packages in your config they are a great way to organize your configuration. The only downside is if you make changes you have to do a full reset. Using the reload automatons and scripts doesn’t work.
First I created an input boolean to serve as my on off switch.
input_boolean:
haunted_mansion:
name: Haunted Mansion
This allows me to use a switch to kick off the sequence in the UI using a picture entity which then lights up indicating it is running. I couldn’t get this to work just using the script.
the input boolean also allows us to trigger it by saying, “Alexa, our time has come.” That bit of magic is simply a Routine setup via the Alexa app that uses a custom voice trigger to turn on a switch. If you have connected your home assistant setup to the echo, I’m using Nabu Casa to do it, then you just need to add your phase, then tell it to turn on the device or input boolean in my case.
I have learned through experience that when you are doing anything automation or script that runs for long than a few seconds you need an emergency cutoff. So I built a kill switch. In this case a script that I labeled kill_this_ride
The purpose of this script is to turn off any scripts that are running, reset lights, and kill any of the audio playing. This doubles as an E-Shutoff and bring up the house lights when it is over.
This script is actually in the disney.yaml.
I won’t detail it here, but it essentially stops the media player service and kills any of the Disney scripts. There is has to be a better way but for the time it works. Bottom line, if you are doing something like this in the middle of your house make sure you can kill it quickly. Your marriage / relationships depend on it.
Once I was sure I could turn things off if it all went wrong, I started to automate the lights.
When the input boolean is turned on it simply starts the audio.
- id: haunted_mansion_on
alias: Haunted Mansion On
initial_state: true
trigger:
- platform: state
entity_id: input_boolean.haunted_mansion
to: 'on'
action:
- service: script.turn_on
entity_id: script.haunted_mansion_start
The actual audio playback is handle via that script.haunted_mansion_start
so that it can be stopped.
haunted_mansion_start:
sequence:
- condition: state
entity_id: input_boolean.audible_notifications
state: 'on'
- condition: state
entity_id: sensor.family_status
state: Home
- service: media_player.volume_set
data_template:
entity_id: media_player.ha_speaker
volume_level: .5
- service: media_player.play_media
entity_id: media_player.ha_speaker
data:
media_content_id: http://192.168.7.40/audio/haunted_mansion_preshow_full.mp3
media_content_type: "music"
The script goes through a couple of conditions.
First, is the audible notifications on. This means it won’t play after people are in bed.
Then, it makes sure we are home. I’m not sure this would ever get triggered by anyone but us, but just in case we have guests over and we are not here we don’t want ti scaring people.
Then it sets the volume, and starts the audio.
Back when this was all on Hassbian, the light effects were in the same script. But now that it’s on via the chromecast, the timing of when the audio starts playing is never consistent. So I needed something I could count on.
So now, I have another automation that starts the light effects when the audio actually starts playing on the chromecast.
- id: haunted_mansion_show_trigger
alias: Haunted Mansion show Trigger
initial_state: true
trigger:
- platform: state
entity_id: media_player.ha_speaker
to: 'playing'
condition:
- condition: state
entity_id: input_boolean.haunted_mansion
state: 'on'
action:
- service: script.turn_on
entity_id: script.haunted_mansion_lights
This tiggers if the chromecast changes to playing then checks to see if the haunted mansion input boolean is actually on. If it is, we kick off the light effects script – script.haunted_mansion_lights
.
Getting this right took a lot of trial an error. And frankly I tweak it a lot. And even with the new light effect trigger, the timing can get off. But until I spend the time to figure out how to get it to play via VLC and the audio jack I don’t think this is the best I got.
The script.haunted_mansion_lights
looks like this:
haunted_mansion_lights:
sequence:
- service: light.turn_on
entity_id: group.rgb_lr
data:
rgb_color: [255,255,255]
- delay: 00:01:06
- service: light.turn_on
entity_id: group.rgb_lr
data:
rgb_color: [73,119,255]
- delay: 00:00:15
- service: light.turn_on
entity_id: group.rgb_lr
data:
brightness_pct: 25
- delay: 00:00:37
- service: switch.turn_on
entity_id: switch.rail_lights
- service: switch.turn_off
entity_id: switch.rail_lights
- delay: 00:00:02
- service: scene.turn_on
data:
entity_id: scene.haunted_lights_out
- service: switch.turn_on
entity_id: switch.rail_lights
- service: switch.turn_off
entity_id: switch.rail_lights
- delay: 00:00:10
- service: light.turn_on
entity_id: group.rgb_lr
data:
rgb_color: [255,255,255]
brightness_pct: 25
- delay:
seconds: 160
It is simply a sequence of light changes followed by delays. Lots of color and brightness changes. I use an old strand of Christmas lights to simulate the lightening. And the delay at the end is to ensure that the lights don’t reset early.
If you want to see the full show I created a video of just the show.
All that was left was turning it off.
The manual way is simply turning off he input boolean, which triggers the haunted_mansion_off
automation which executes a series of scripts to reset everything.
- id: haunted_mansion_off
alias: Haunted Mansion Off
initial_state: true
trigger:
- platform: state
entity_id: input_boolean.haunted_mansion
to: 'off'
action:
- service: script.kill_this_ride
- service: media_player.media_stop
entity_id: media_player.ha_speaker
- service: script.turn_off
entity_id: script.haunted_mansion_lights
I need to figure out a better way to handle the end of the show. On Hassbian I had a sensor that watched VLC and when it quit it it triggered an automation to turn off the input boolean. I tried just watching the state of the Chromecast and using the state change from player to idle. But that resulted in false positives. I may just have to put in a timer and rest after X minutes.
And that is basically how I turned my living room the Haunted Mansion. Of course it also set me down a path adding a ton of other Disney content to my house. Don’t believe me? Just look at the disney.yaml file.
Anyway there is a lot more tweaking to do to get this just right.
Until then next time…go automate something.
Oh…wait, if you want to see the video version of this…