From 8a8997750e9f3d38ec94eebfbcf9b2f113e7e3a5 Mon Sep 17 00:00:00 2001 From: Tanner Date: Sat, 13 Jun 2026 11:30:45 -0600 Subject: [PATCH] Idk what this is --- main.py | 35 +++++++++++++++++++++++++++++++++-- unifi.py | 25 +++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 588de1e..a73332f 100644 --- a/main.py +++ b/main.py @@ -28,6 +28,8 @@ RELAY_OFF = True cooldown_time = time.time() +FAIL_COUNT = 0 + def set_relay(pin, state): if IS_PI: GPIO.output(pin, state) logging.info('Set relay on pin %s to %s', pin, 'ON' if state == RELAY_ON else 'OFF') @@ -48,12 +50,20 @@ def ring_bell(camera): try: doorbell = settings.DOORBELLS[camera] + logging.info('Ringing doorbell: %s', doorbell['name']) pulse_relay(doorbell['gpio']) except KeyError: logging.error('Doorbell %s not found!', camera) async def process_message(msg): + global FAIL_COUNT + + if msg == 'CONNECTED': + logging.info('Connected to websocket. Listening for messages...') + FAIL_COUNT = 0 + return + if msg.get('type', '') != 'ring': return @@ -62,12 +72,15 @@ async def process_message(msg): ring_bell(msg['camera']) async def main(): + global FAIL_COUNT + while True: try: async for msg in unifi.connect(): await process_message(msg) except BaseException as e: - logging.exception('Error connecting to Unifi Protect: %s. Trying again...', str(e)) + FAIL_COUNT += 1 + logging.error('Problem connecting to Unifi Protect: %s - %s, fail count: %s', e.__class__.__name__, e, FAIL_COUNT) await asyncio.sleep(5) @@ -93,6 +106,23 @@ def init(): signal(sig, disable_relays_on_exit) logging.info('Signals initialized') + +async def watchdog(): + global FAIL_COUNT + + logging.info('Starting watchdog...') + + while True: + await asyncio.sleep(1) + + if FAIL_COUNT >= 10: + logging.info('Too many failures, starving watchdog...') + continue + + with open('/dev/watchdog', 'w') as wdt: + wdt.write('1') + + if __name__ == '__main__': logging.info('') logging.info('======================================') @@ -100,5 +130,6 @@ if __name__ == '__main__': init() loop = asyncio.get_event_loop() + if not DEBUG: + a = loop.create_task(watchdog()) loop.run_until_complete(main()) - loop.close() diff --git a/unifi.py b/unifi.py index d12deaf..47d5cdf 100644 --- a/unifi.py +++ b/unifi.py @@ -1,3 +1,10 @@ +import os, logging +DEBUG = os.environ.get('DEBUG') +logging.basicConfig( + format='[%(asctime)s] %(levelname)s %(module)s/%(funcName)s - %(message)s', + level=logging.DEBUG if DEBUG else logging.INFO) +logging.getLogger('aiohttp').setLevel(logging.DEBUG if DEBUG else logging.WARNING) + import asyncio import aiohttp import zlib @@ -15,12 +22,24 @@ async def connect(): rememberMe=True, ) + logging.info('Connecting to Unifi Protect...') + async with aiohttp.ClientSession() as session: - async with session.post(settings.UFP_ADDRESS + '/api/auth/login', json=data, ssl=False) as resp: + async with session.post(settings.UFP_ADDRESS + '/api/auth/login', json=data, ssl=False, timeout=5) as resp: cookie = resp.cookies['TOKEN'] + logging.info('Got cookie.') + headers = {'cookie': cookie.key + '=' + cookie.value} - async with session.ws_connect(settings.UFP_ADDRESS + '/proxy/protect/ws/updates', headers=headers, ssl=False) as ws: + async with session.ws_connect( + settings.UFP_ADDRESS + '/proxy/protect/ws/updates', + headers=headers, + ssl=False, + receive_timeout=10.0, + heartbeat=10.0, + ) as ws: + yield 'CONNECTED' + async for msg in ws: packet_type, payload_format, deflated, unknown, payload_size = struct.unpack('!bbbbi', msg.data[0:HEADER_LENGTH]) action_start = HEADER_LENGTH @@ -30,6 +49,8 @@ async def connect(): yield json.loads(data_packet.decode()) + logging.info('Lost connection to web socket.') + async def test(): async for msg in connect():