It’s that spooky time of year again, but this time it can be extra spooky with the help of home automation.
Motion-activated jumpscare on TV
One classic spooky thing to do is have a TV do something scary when people walk by. This is easier than ever on any TV now that everyone has Raspberry Pi with HDMI output and z-wave (or other) motion sensors everywhere. Check this out:
Yeah so there’s a Raspberry Pi behind the TV running a simple program that monitors a MQTT topic for a trigger. Meanwhile the motion sensor triggers an automation in Home Assistant (running elsewhere in the house) that publishes the MQTT message that sets it off. There’s also a z-wave switch back there that turns on the strobe light. (You could alternatively have Home Assistant running on the same pi you have behind the TV if you wanted and avoid the MQTT thing and just trigger the program directly.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- alias: Boo trigger: platform: state entity_id: binary_sensor.zooz_motion to: 'on' action: - service: mqtt.publish data: topic: home/halloween/boo payload: 'boo' - service: switch.turn_on entity_id: switch.lavalamp_switch - delay: '00:00:15' - service: switch.turn_off entity_id: switch.lavalamp_switch |
The program on the pi is derived from infopanel so reuses some MQTT config stuff. You can make it simpler if you want. The key commands to run are:
- Â Scary jump:
p = subprocess.call(['omxplayer','-o', 'hdmi', 'jumpscare.mp4'])
- And then corny scene at way lower volume:
p = subprocess.Popen(['omxplayer','-o', 'hdmi', '--vol', '-1200','--loop', 'halloween3.mp4'])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
"""MQTT client to get data into the display from some data source.""" import logging import inspect import time import subprocess import paho.mqtt.client as mqtt import yaml import voluptuous as vol LOG = logging.getLogger(__name__) logging.basicConfig(level=logging.DEBUG) MQTT = vol.Schema({'broker': str, vol.Optional('port', default=1883): int, 'client_id': str, vol.Optional('keepalive', default=60): int, vol.Optional('username'): str, vol.Optional('password'): str, vol.Optional('certificate'): str, vol.Optional('protocol', default=4): vol.Coerce(int), 'topic': str}) SCHEMA = vol.Schema({'mqtt': MQTT, }) def load_config_yaml(path): """Load and validate config file as an alternative to command line options.""" with open(path) as configfile: config = yaml.load(configfile) config = SCHEMA(config) return config class MQTTClient(object): """MQTT Client.""" def __init__(self, conf): """Construct the MQTT client.""" self._client = None self.conf = conf self._last_process = None def on_connect(self, client, userdata, flags, rc): # pylint: disable=unused-argument, invalid-name """Do callback for when MQTT server connects.""" LOG.info("Connected with result code %d", rc) client.subscribe(self.conf['topic']) # subscribe in case we get disconnected def on_message(self, client, userdata, msg): # pylint: disable=unused-argument """Do callback for when MQTT receives a message.""" LOG.debug("%s %s", msg.topic, str(msg.payload)) key = msg.topic.split('/')[-1] cmd = msg.payload.decode() if cmd == 'boo': self._last_process = boo(self._last_process) elif cmd == 'stop': self._last_process.terminate() def start(self): """Connect to the MQTT server.""" conf = self.conf LOG.info('Connecting to MQTT server at %s', conf['broker']) self._client = mqtt.Client(conf['client_id'], protocol=conf['protocol']) self._client.on_connect = self.on_connect self._client.on_message = self.on_message if conf.get('username'): self._client.username_pw_set(conf['username'], conf['password']) if conf.get('certificate'): self._client.tls_set(conf['certificate']) self._client.connect(conf['broker'], conf['port'], conf['keepalive']) self._client.loop_start() def stop(self): """End the MQTT connection.""" self._client.loop_stop() def boo(process): print('BOO!') if process: print('Killing {}'.format(process)) subprocess.call(['sudo', 'killall','omxplayer.bin']) #p = subprocess.call(['omxplayer','-o', 'hdmi', 'halloween_mix.mp4']) #p = subprocess.call(['omxplayer','-o', 'hdmi', 'blade_clip3.mp4']) p = subprocess.call(['omxplayer','-o', 'hdmi', 'jumpscare.mp4']) p = subprocess.Popen(['omxplayer','-o', 'hdmi', '--vol', '-1200','--loop', 'halloween3.mp4']) #p = subprocess.call(['vlc','--no-loop', 'halloween_mix.mp4', 'vlc://quit']) #p = subprocess.Popen(['vlc','halloween3.mp4','-L']) return p if __name__ == '__main__': conf = load_config_yaml('halloween.yaml') client = MQTTClient(conf['mqtt']) client.start() while True: time.sleep(0.25) |
Subtle changing light colors
This isn’t actually spooky but it’s pretty neat for ambiance. It’s just two Hue bulbs that swap colors ever 2.5 minutes. I dunno, I think it’s sweet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
- alias: LightDance trigger: platform: time minutes: '/5' seconds: 00 action: - service: light.turn_on data: entity_id: light.clip_on transition: 10 rgb_color: - 255 - 70 - 0 - service: light.turn_on data: entity_id: light.bedroom transition: 10 rgb_color: - 192 - 5 - 255 - delay: '00:02:30' - service: light.turn_on data: entity_id: light.bedroom transition: 10 rgb_color: - 255 - 70 - 0 - service: light.turn_on data: entity_id: light.clip_on transition: 10 rgb_color: - 192 - 5 - 255 |
Keep the lights red
Philips Hue lights announced that they’d let you set the default color when they turn on but as of posting this it’s not out yet. So when I wanted red lights I was worried that someone might flip the switch ruining the ambiance. Thus I needed an automation to keep making them red all the time, just in case.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
- alias: Red light on trigger: platform: time minutes: '/2' seconds: 00 condition: condition: and conditions: - condition: template value_template: '{{ states.light.living_room.attributes.brightness == 254 }}' action: - service: light.turn_on data: entity_id: light.living_room transition: 5 rgb_color: - 255 - 0 - 0 - service: light.turn_on data: entity_id: light.bathroom transition: 5 rgb_color: - 255 - 0 - 0 |
Topical infopanel messages
Here I configured the infopanel to have a nice witch and a pumpkin. The witch says things that are scary to medical professionals or to engineers (most of the people coming to the Halloween party). I guess most of these are pretty obscure but I thought it was hilarious. Customize to your audience.
Infopanel config:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
pumpkin: type: Sprite ticks_per_frame: 5 reverse_frame_loop: False pallete: 1: - 42 - 189 - 55 2: - 255 - 144 - 36 3: - 0 - 0 - 0 text: - 255 - 144 - 36 frames: - 0000000011000000 0000000110000000 0000001100000000 0002011112220000 0222221122222200 2222222222222220 2223322223322220 2223322223322220 2222222222222220 0222223332222220 0222223232222200 0022223332222200 0002222222200000 0000000000000000 - 0000000110000000 0000001100000000 0000011000000000 0002011112220000 0222221122222200 0222222222222220 2222332222332222 2222332222332222 0222222222222222 0222223332222220 0222223232222200 0022223332222200 0002222222200000 0000000000000000 phrases: - DERP - LA LA - HO HUM - DOOP - DUH - MEOW - WOOF - NOM NOM - BOOP - BEEP - MOO - QUACK - BOP - LIKE - "CAN'T EVEN" - GOO GOO - HE HAW witch: type: Sprite ticks_per_frame: 7 max_ticks_per_phrase: 175 min_ticks_per_phrase: 50 reverse_frame_loop: False pallete: 1: - 255 - 240 - 0 2: - 49 - 215 - 88 3: - 189 - 77 - 16 4: - 255 - 255 - 253 5: - 77 - 76 - 54 text: [0,150,255] frames: - 0000000000500000 0000000000550000 0000000000550000 0000000005555000 0000000055555500 0000000002424000 0000000002222000 0000000005200000 0000000055500000 1000000550500000 1100005500500000 1111335333333300 1110055000000000 1110550000000000 1000055000000000 0000000000000000 - 0000000000050000 0000000000550000 0000000000550000 0000000005555000 0000000055555500 0000000004242000 0000000002222000 0000000005200000 0000000055500000 1100000550500000 1110005500500000 1111335333333300 1110055000000000 1000550000000000 0000055000000000 0000000000000000 phrases: - BOO - YAR - FUCK - SHIT - SPOOK - ASS - NYA HAHA! - HOT TUB - HI LAURA - BREW - SHOTS! - TRUMP - "I'M LATE" - "POST CALL" - "RISK DAY" - "DIABETES" - "HYPERTENSION" - CALCIPHYLAXIS - RABIES - ALS - OBESITY - BED SORES - EMBOLUS - LINEN SHORTAGE - HAMMER PAGE - CODE SEPSIS - SHOCK - SCONE DAY - VA HOTTRAY - TRAFFIC - "CESIUM-137" - DOE BAN - ANTI-NUKES - CLIMATE CHNG - "VOID WORTH" - STOCHASTICITY - TRANSIENTS - CLAD STRAIN - INTERVENERS - PROLIFERATION - SCRAM - INFARCT - NECROSIS - MDRO - ANTI-VAX - OBAMACARE - STROKE |
Hi! Very cool, if you want to have fun with home automation and voice, you can take a look at what we are building at Snips https://snips.ai, it can even integrate with Home Assistant