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

73
main.py
View file

@ -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()