Various improvements

* Remove werkplaats, as the sensor topic was incorrect
* Catch exceptions from subscribe.simple
* Make MQTT_HOST configurable
* Terminate if env vars are unset
This commit is contained in:
polyfloyd 2023-09-10 15:45:25 +02:00
parent 274adf9f32
commit 3c4439454b

65
main.py
View file

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