Skip to content

Instantly share code, notes, and snippets.

@MarkBaggett
Last active Mar 31, 2020
Embed
What would you like to do?
Notes on an escape room using home assistant.
As requested here is a walk through for the "Escape room" challenge I threw together for a party at my house. This was developeed in about 5 hours. It took guests about 45 minutes to complete. I have several things I would like to do to improve it over the next could iterations.
Notes to the reader:
- Requires Home Assistant https://www.home-assistant.io
- Requires App Daemon https://www.home-assistant.io/docs/ecosystem/appdaemon/
- My home includes Philips Hue lights, Ecobee thermostat, arlo cameras, some smart TV's and other devices used in the challenges.
- It is not shown in the code below but I also have printed puzzles and ammo boxes with combination locks throughout the house. Generally a printed puzzle leads players to physical activity that triggers a "smart home puzzle" which leads them to a combination to unlock the next ammo box containing the next printed puzzle. Lather, rince, repeat.
- Not all puzzles are published here but this is enough to get your creative juices flowing.
- The "announce" function in the code below is part of a custom module (now shared) that I wrote to interfaces with my Lyrics OnQ home intercom system. It turns on speakers through out the entire house and does text to speak announcements. You can replace this with any similar functionality you have in your home. My announce function uses Google Text to speach to have my laptop speak to the nearby echo. The Echo is plugged into my home intercom system and it repeats the phrase through out the entire house.
def announce(words):
sentence = "Alexa simon says {0}".format(words)
cli = 'gtts-cli -ss "{0}" | play -t mp3 -'.format(sentence)
os.system(cli)
time.sleep( 3 + len(words.split()) )
- my home assistant configuration has several "input-boolean" switches including one to start the escape game when the switch goes from from off to on. The game starts with a "listen_state" subscription to that switch.
class EscapeGame(hass.Hass):
def initialize(self):
# Subscribe to presence changes
self.listen_state(self.start_game,'input_boolean.escape_game', old = 'off', new = 'on' )
#When switch is turn is turned on it calls the start_game method. It turns the switch back off, gives instructions and turns off all other switches used by the game. I have several "override" switches I can through if a player finishes the challenge but the system fails to recognize it in a reasonable amount of time. For example, my current method of checking for motion on the Arlo cameras sometimes take 5 minutes to discover.
def start_game(self, entity, attribute, old, new, kwargs):
self.log("THE GAME HAS STARTED !")
#Turn back off the game start switch (providing feedback that it started)
self.turn_off('input_boolean.escape_game')
#Use television in living room to explain how to play the game.
self.call_service("tts/google_say", entity_id="media_player.bravia_tv", message="Welcome. You will have 45 minute to solve all of the clues and return to this room. insert first clue here. READY,,,GO")
#Turn off all other switches incorporated into the game
self.turn_off("input_boolean.escape_game_puzzle1")
self.turn_off("input_boolean.escape_game_puzzle2")
self.turn_off("input_boolean.escape_game_puzzle3")
self.turn_off("input_boolean.escape_game_puzzle4")
self.turn_off("input_boolean.escape_game_puzzle5")
#call each of the challenge puzzles
self.challenge_puzzle1()
self.challenge_puzzle2()
self.challenge_puzzle3()
self.challenge_puzzle4()
self.challenge_puzzle5()
def challenge_puzzle1(self):
#Starts downstairs when someone triggers the first puzzle from clue#1
self.log("Starting Light Challenge")
self.turn_on("light.living_room")
self.turn_on("light.downstairs_hallway")
self.log("Now watching light pattern")
self.call_service("tts/google_say", entity_id="media_player.bravia_tv", message="Clue #1 goes here.")
while not self.lightpattern():
time.sleep(2)
self.log("Pattern Satisfied!!!")
announce("Drop the next clue")
def lightpattern(self):
#This function returns True if the lights are setup to a specific pattern
center = self.get_state("light.livingroom_center") == "on"
top = self.get_state("light.livingroom_top") == "on"
right = self.get_state("light.livingroom_right") == "off"
left = self.get_state("light.livingroom_left") == "off"
hallmaster = self.get_state("light.downstairs_hallway_near_master") == "off"
hallkitchen = self.get_state("light.downstairs_hallway_near_kitchen")=='on'
lightcolor= self.get_state("light.livingroom_center", attribute="rgb_color")
#while loop because it returns None when color lights are not set to a color (ie just turned on)
while not lightcolor:
lightcolor= self.get_state("light.livingroom_center", attribute="rgb_color")
if not lightcolor:
self.log("error getting light color") time.sleep(2)
isred = (lightcolor[0]==255 and lightcolor[2]==0)
self.log(str([isred,lightcolor,center,top,right,left,right,hallmaster,hallkitchen]))
return all([isred,center,top,right,left,right,hallmaster,hallkitchen])
def challenge_puzzle2(self):
#must have a clue indiate order to put the blinking lights in to get the combination to ammo box #2
#Combo unlocks ammo box that tells them to set downstairs temp to 93 and upstairs to 72
self.log("Starting combolights until temp is correct.")
while int(self.get_state('climate.ecobee_down',attribute='temperature'))!=93 and int(self.get_state('climate.ecobee_up',attribute='temperature'))!=72:
self.blink_light('light.media_front_left','red',4)
time.sleep(3)
self.blink_light('light.media_front_right','green',9)
time.sleep(3)
self.blink_light('light.media_back_left','blue',5)
time.sleep(3)
self.blink_light('light.media_back_right','purple',6)
#combo is 549 because clue card indicates order of "blue red green"
self.log("Combo Challenge is done.")
def blink_light(self, entity_id, color, pulse_count):
self.log("start blinking {} color {} {}".format(entity_id, color, col))
for x in range(0,pulse_count):
self.turn_on(entity_id, color_name = color, brightness='255')
time.sleep(1)
self.turn_off(entity_id)
time.sleep(1)
#When done blinking set light back to white.
self.turn_on(entity_id, color_name = "white", brightness='255')
self.log("done blinking {} {}".format(entity_id,color))
#Here are some other things I have incorporate into the game...
#Check to see if someone is lying in bed..
if self.get_state("binary_sensor.sleepnumber_mark_in_bed")=="on":
#Play Europe "The Final Count" down when there is 5 minutes left in the game.
self.call_service("media_extractor/play_media",entity_id="media_player.bravia_tv", media_content_id="https://www.youtube.com/watch?v=9jK-NcRmVcw", media_content_type="video/mp4")
#check motion cameras to see if the number of videos recorded has increased..
self.get_state('sensor.captured_today_arlo1')
#reset ecobee thermostats after people have change the temperature to a specific combination (so it doesnt actually heat to 93 degrees)
self.call_service("climate/ecobee_resume_program",entity_id="climate.ecobee_down")
#Use harmony remote to type "combination" repeatedly on the television. Be careful to choose a combo that is not associated with a channel that has content that might be mistaken as a clue.
self.send_command(“remote/send_command”, entity_id= “remote.harmony”, device=”CableBoxIDNumber”, command = [“1”,”8”,”5”,”2”] )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment