From 6f609ac43c4ae05958b3f294e0b4719a04291a16 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sun, 30 Jan 2022 17:53:35 -0700 Subject: [PATCH] Convert doorbell to use rtl_433 and mqtt --- main.py | 88 +++++++++++++++++++++++++++++++++++++++++------- requirements.txt | 3 +- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index dd9db3f..ab84685 100644 --- a/main.py +++ b/main.py @@ -7,39 +7,103 @@ logging.basicConfig(stream=sys.stdout, import time import json +import asyncio +from asyncio_mqtt import Client import pygame import secrets +COOLDOWN = time.time() + CHIME = 'chime.ogg' -FRONTDOOR = 'frontdoor.ogg' -BACKDOOR = 'backdoor.ogg' -def play_sound(filename): +DOORBELLS = { + '647166': { + 'name': 'Front Door', + 'sound': 'frontdoor.ogg', + }, + '549660': { + 'name': 'Back Door', + 'sound': 'backdoor.ogg', + } +} + +async def play_sound(filename): pygame.mixer.music.load(filename) pygame.mixer.music.play() logging.info('Playing sound %s', filename) while pygame.mixer.music.get_busy(): - pygame.time.Clock().tick(10) + #pygame.time.Clock().tick(10) + await asyncio.sleep(0.1) + + +async def ring_bell(sound): + global COOLDOWN + if time.time() - COOLDOWN < 5.0: + logging.info('Cooldown skipping.') + return + COOLDOWN = time.time() + + await asyncio.sleep(0.1) + + await play_sound(CHIME) + await play_sound(sound) + + await asyncio.sleep(0.75) + + await play_sound(CHIME) + await play_sound(sound) + + logging.info('Done ringing.') + +async def process_mqtt(message): + text = message.payload.decode() + topic = message.topic + logging.info('MQTT topic: %s, message: %s', topic, text) -def backdoor(): - play_sound(CHIME) - play_sound(BACKDOOR) + if not topic.startswith('rtl_433'): + logging.info('Invalid topic, returning') + return - time.sleep(0.75) + try: + data = json.loads(text) + except json.JSONDecodeError: + logging.info('Invalid json, returning') + return + + id_ = str(data.get('id', '')) + + if id_ not in DOORBELLS: + logging.info('Invalid id, returning') + return + + doorbell = DOORBELLS[id_] + + logging.info('Ringing %s...', doorbell['name']) + + await ring_bell(doorbell['sound']) + + +async def fetch_mqtt(): + await asyncio.sleep(3) + async with Client('localhost') as client: + async with client.filtered_messages('#') as messages: + await client.subscribe('#') + async for message in messages: + loop = asyncio.get_event_loop() + loop.create_task(process_mqtt(message)) - play_sound(CHIME) - play_sound(BACKDOOR) if __name__ == '__main__': logging.info('') logging.info('==========================') logging.info('Booting up...') + pygame.init() pygame.mixer.pre_init(buffer=4096) pygame.mixer.init(buffer=4096) - backdoor() - + loop = asyncio.get_event_loop() + loop.run_until_complete(fetch_mqtt()) diff --git a/requirements.txt b/requirements.txt index 142a6b0..0892f7f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,9 @@ +asyncio-mqtt==0.12.1 certifi==2021.5.30 charset-normalizer==2.0.6 idna==3.2 numpy==1.21.2 -paho-mqtt==1.5.1 +paho-mqtt==1.6.1 pandas==1.3.3 pycryptodome==3.10.4 pygame==2.0.1