import asyncio import aiomqtt from discord_webhook import DiscordEmbed import commands.bottleclip as bottleclip _mqtt_host = None def setup(bot, mqtt_host): global _mqtt_host _mqtt_host = mqtt_host # !state bot.command(description="Bitlair Space State")(state) # !co2 bot.command(description="co2 levels")(co2) # !temp bot.command(description="Temperature")(temp) # !humid bot.command(description="Humidity")(humid) # !np bot.command(description="Now Playing")(np) # !bottleclip bot.command( name="bottleclip", description="Generate a bottle-clip STL file suitable for printing", )(bottleclip.command) async def mqtt_get_one(topic, timeout=20): async with asyncio.timeout(timeout): async with aiomqtt.Client(_mqtt_host) as mq: await mq.subscribe(topic) return await anext(mq.messages) async def state(ctx): async with ctx.typing(): try: msg = await mqtt_get_one("bitlair/state") space_state = msg.payload.decode("ascii") if space_state == "open": await ctx.reply("Bitlair is OPEN! :sunglasses:") elif space_state == "closed": await ctx.reply("Bitlair is closed :pensive:") except Exception as err: await ctx.reply("Meh, stuk") raise err async def co2(ctx, where="hoofdruimte"): async with ctx.typing(): try: msg = await mqtt_get_one(f"bitlair/climate/{where}/co2_ppm") await ctx.reply(f"{where}: {msg.payload.decode('ascii')} ppm\n") except Exception as err: await ctx.reply("Meh, stuk") raise err async def temp(ctx, where="hoofdruimte"): async with ctx.typing(): try: msg = await mqtt_get_one(f"bitlair/climate/{where}/temperature_c") await ctx.reply(f"{where}: {msg.payload.decode('ascii')} °C\n") except Exception as err: await ctx.reply("Meh, stuk") raise err async def humid(ctx, where="hoofdruimte"): async with ctx.typing(): try: msg = await mqtt_get_one(f"bitlair/climate/{where}/humidity_pct") await ctx.reply(f"{where}: {msg.payload.decode('ascii')} pct\n") except Exception as err: await ctx.reply("Meh, stuk") raise err async def np(ctx): async with ctx.typing(): await ctx.reply("Now playing: Darude - Sandstorm") async def run_events(mqtt_host): retained = { "bitlair/alarm", "bitlair/photos", "bitlair/state", "bitlair/state/djo", } async with aiomqtt.Client(mqtt_host) as mq: await asyncio.gather(*[mq.subscribe(topic) for topic in retained]) async for msg in mq.messages: # Retained messages trigger an initial message on connecting. Prevent relaying them to Discord on startup. if str(msg.topic) in retained: retained.remove(str(msg.topic)) continue payload = msg.payload.decode("ascii") if msg.topic.matches("bitlair/alarm"): yield f"Alarm: {payload}" elif msg.topic.matches("bitlair/state"): yield f"Bitlair is now {payload.upper()}" elif msg.topic.matches("bitlair/state/djo"): yield f"DJO is now {payload.upper()}" elif msg.topic.matches("bitlair/photos"): embed = DiscordEmbed(title="WIP Cam", color="fc5d1d") embed.set_url(f"https://bitlair.nl/fotos/view/{payload}") embed.set_image(f"https://bitlair.nl/fotos/photos/{payload}") yield embed else: continue