diff --git a/main.py b/main.py index 3639b0f..0c2e130 100755 --- a/main.py +++ b/main.py @@ -2,68 +2,86 @@ # Bitlair HobbyBot +import asyncio +from typing import Optional from time import sleep from string import Template from discord import Intents from discord.ext import commands -from discord_webhook import DiscordWebhook,DiscordEmbed -import datetime +from discord_webhook import DiscordWebhook, DiscordEmbed +from datetime import datetime import pytz import paho.mqtt.client as mqtt import paho.mqtt.subscribe as subscribe import os +import sys +mqtt_host = os.getenv('MQTT_HOST') +if not mqtt_host: + print('MQTT_HOST unset') + sys.exit(1) + token = os.getenv('DISCORD_TOKEN') +if not token: + print('DISCORD_TOKEN unset') + sys.exit(1) + webhook_url = os.getenv('DISCORD_WEBHOOK_URL') -description = 'Bitlair Bot' -state_template = Template('$topic is now $state') +if not webhook_url: + print('DISCORD_WEBHOOK_URL unset') + sys.exit(1) + timezone = pytz.timezone('Europe/Amsterdam') # Discord bot stuff intents = Intents.default() intents.message_content = True intents.members = True -HobbyBot = commands.Bot(command_prefix='!', description=description, intents=intents) +HobbyBot = commands.Bot(command_prefix='!', description='Bitlair Bot', intents=intents) +def mqtt_get_one(topic): + try: + msg = subscribe.simple(topic, hostname=mqtt_host, keepalive=10) + return msg.payload.decode() + except err: + print(err) + return '' # Define bot commands @HobbyBot.event async def on_ready(): print(f'Logged in as {HobbyBot.user} (ID: {HobbyBot.user.id})') -# !state +# !state @HobbyBot.command(description='Bitlair Space State') async def state(ctx): async with ctx.typing(): - spaceState = subscribe.simple("bitlair/state", hostname="bitlair.nl").payload.decode() + spaceState = mqtt_get_one("bitlair/state") if spaceState == "open": await ctx.send("Bitlair is OPEN! :sunglasses:") elif spaceState == "closed": await ctx.send("Bitlair is closed :pensive:") -# !co2 +# !co2 @HobbyBot.command(description='co2 levels') async def co2(ctx): async with ctx.typing(): - hoofdruimte = subscribe.simple("bitlair/climate/hoofdruimte_ingang/co2_ppm", hostname="bitlair.nl").payload.decode() - werkplaats = subscribe.simple("bitlair/climate/werkplaats/co2_ppm", hostname="bitlair.nl").payload.decode() - await ctx.send("Hoofdruimte: " + hoofdruimte + " ppm\nWerkplaats: " + werkplaats + " ppm") -# !temp + hoofdruimte = mqtt_get_one("bitlair/climate/hoofdruimte_ingang/co2_ppm") + await ctx.send("Hoofdruimte: %s ppm\n" % hoofdruimte) +# !temp @HobbyBot.command(description='Temperature') async def temp(ctx): async with ctx.typing(): - hoofdruimte = subscribe.simple("bitlair/climate/hoofdruimte_ingang/temperature_c", hostname="bitlair.nl").payload.decode() - werkplaats = subscribe.simple("bitlair/climate/werkplaats/temperature_c", hostname="bitlair.nl").payload.decode() - await ctx.send("Hoofdruimte: " + hoofdruimte + "°C\nWerkplaats: " + werkplaats + "°C") + hoofdruimte = mqtt_get_one("bitlair/climate/hoofdruimte_ingang/temperature_c") + await ctx.send("Hoofdruimte: %s °C\n" % hoofdruimte ) # !humid @HobbyBot.command(description='Humidity') async def humid(ctx): async with ctx.typing(): - hoofdruimte = subscribe.simple("bitlair/climate/hoofdruimte_ingang/humidity_pct", hostname="bitlair.nl").payload.decode() - werkplaats = subscribe.simple("bitlair/climate/werkplaats/humidity_pct", hostname="bitlair.nl").payload.decode() - await ctx.send("Hoofdruimte: " + hoofdruimte + " pct\nWerkplaats: " + werkplaats + " pct") + hoofdruimte = mqtt_get_one("bitlair/climate/hoofdruimte_ingang/humidity_pct") + await ctx.send("Hoofdruimte: %s pct\n" % hoofdruimte) # !np @HobbyBot.command(description='Now Playing') @@ -85,19 +103,16 @@ def on_message(client, userdata, msg): topic = msg.topic msg = msg.payload.decode() + state_template = Template('$topic is now $state') if topic == "bitlair/state/bitlair": - topic = topic.split("/")[2].capitalize() - msg = state_template.substitute(topic=topic, state=msg.upper()) + msg = state_template.substitute(topic='Bitlair', state=msg.upper()) elif topic == "bitlair/state/djo": - topic = topic.split("/")[2].upper() - msg = state_template.substitute(topic=topic, state=msg.upper()) - else: return - webhook = DiscordWebhook(url=webhook_url, rate_limit_retry=True) - embed = DiscordEmbed(title='MQTT', description=msg, color=15105570, timestamp=datetime.datetime.now(tz = timezone).isoformat()) - webhook.add_embed(embed) + msg = state_template.substitute(topic='DJO', state=msg.upper()) + else: + return + webhook = DiscordWebhook(url=webhook_url, rate_limit_retry=True, content=msg) webhook.execute() - # prevent triggering rate limits - sleep(1) + sleep(1) # Prevent triggering rate limits. except Exception as e: print(e) @@ -105,7 +120,7 @@ def on_message(client, userdata, msg): client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message -client.connect("bitlair.nl", 1883, 60) +client.connect(mqtt_host, 1883, 60) # Start mqtt loop and discord bot client.loop_start()