aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2023-12-08 10:20:36 +0100
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2023-12-29 07:29:15 +0100
commit5973b7ca26e63880e9d74a52fa9e2ec61c811401 (patch)
tree818b1d3e0a9daeb9561c8771f2dea06e906bf693
parent0a56d27c3b0f590e0eef85666bb0d10d36041089 (diff)
Management command for the mqtt loop
-rw-r--r--kerbana/settings.py7
-rw-r--r--rrd/management/__init__.py0
-rw-r--r--rrd/management/commands/__init__.py0
-rw-r--r--rrd/management/commands/listen_mqtt.py10
-rw-r--r--rrd/mqtt.py64
-rw-r--r--rrd/tests/__init__.py0
-rw-r--r--rrd/tests/test_django.py (renamed from rrd/tests.py)2
-rw-r--r--rrd/tests/test_mqtt.py30
8 files changed, 113 insertions, 0 deletions
diff --git a/kerbana/settings.py b/kerbana/settings.py
index 7be9578..f0ba3f2 100644
--- a/kerbana/settings.py
+++ b/kerbana/settings.py
@@ -37,6 +37,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'rrd',
]
MIDDLEWARE = [
@@ -123,3 +124,9 @@ STATIC_URL = '/static/'
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
+MQTT_SERVER = "test.mosquitto.org"
+MQTT_PORT = 1883
+MQTT_USER = None
+MQTT_PASSWORD = None
+MQTT_TOPIC = "kerbana/#"
diff --git a/rrd/management/__init__.py b/rrd/management/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rrd/management/__init__.py
diff --git a/rrd/management/commands/__init__.py b/rrd/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rrd/management/commands/__init__.py
diff --git a/rrd/management/commands/listen_mqtt.py b/rrd/management/commands/listen_mqtt.py
new file mode 100644
index 0000000..758a4f2
--- /dev/null
+++ b/rrd/management/commands/listen_mqtt.py
@@ -0,0 +1,10 @@
+from django.core.management.base import BaseCommand
+
+import rrd.mqtt
+
+class Command(BaseCommand):
+ help = "Listen to mqtt events and update rrd files and graphs"
+
+ def handle(self, *args, **kw):
+ mqtt_client = rrd.mqtt.MQTTClient()
+ mqtt_client.loop_forever()
diff --git a/rrd/mqtt.py b/rrd/mqtt.py
new file mode 100644
index 0000000..713d837
--- /dev/null
+++ b/rrd/mqtt.py
@@ -0,0 +1,64 @@
+import logging
+
+import django.conf
+import paho.mqtt.client as mqtt
+
+
+log = logging.getLogger(__name__)
+
+
+class MQTTClient:
+ def __init__(self):
+ self.reconnect = True
+ self.connected = False
+
+ self.client = mqtt.Client()
+ self.client.on_connect = self.on_connect
+ self.client.on_disconnect = self.on_disconnect
+ self.client.on_message = self.on_message
+
+ def loop_forever(self):
+ self.connect()
+ self.client.loop_forever()
+
+ def loop_start(self):
+ self.connect()
+ self.client.loop_start()
+
+ def loop_stop(self):
+ self.disconnect(reconnect=False)
+ self.client.loop_stop()
+
+ def connect(self):
+ try:
+ self.client.connect(
+ django.conf.settings.MQTT_SERVER,
+ django.conf.settings.MQTT_PORT,
+ 60, # TODO: make the keepalive configurable
+ )
+ except OSError as e:
+ log.debug("Could not connect to MQTT server")
+ log.debug(e)
+
+ def disconnect(self, reconnect: bool = True):
+ self.reconnect = reconnect
+ self.client.disconnect()
+
+ def on_connect(self, client, userdata, flags, rc):
+ log.info("Connected to MQTT")
+ self.connected = True
+ client.subscribe(django.conf.settings.MQTT_TOPIC)
+
+ def on_disconnect(self, client, userdata, rc):
+ log.info("Disconnected from MQTT")
+ self.connected = False
+ if self.reconnect:
+ self.connect()
+
+ def on_message(self, client, userdata, msg):
+ print(
+ "Received msg %s %s", msg.topic, msg.payload.decode()
+ )
+ log.debug(
+ "Received msg %s %s", msg.topic, msg.payload.decode()
+ )
diff --git a/rrd/tests/__init__.py b/rrd/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rrd/tests/__init__.py
diff --git a/rrd/tests.py b/rrd/tests/test_django.py
index 7ce503c..e0fbb45 100644
--- a/rrd/tests.py
+++ b/rrd/tests/test_django.py
@@ -1,3 +1,5 @@
from django.test import TestCase
# Create your tests here.
+
+
diff --git a/rrd/tests/test_mqtt.py b/rrd/tests/test_mqtt.py
new file mode 100644
index 0000000..4ea0852
--- /dev/null
+++ b/rrd/tests/test_mqtt.py
@@ -0,0 +1,30 @@
+import time
+
+import django.test
+
+from .. import mqtt
+
+class TestMQTT(django.test.TestCase):
+ def setUp(self):
+ self.mqtt = mqtt.MQTTClient()
+ self.mqtt.loop_start()
+ time.sleep(0.1)
+ if not self.mqtt.connected:
+ self.skipTest("Could not find an mqtt server")
+
+ def tearDown(self):
+ self.mqtt.loop_stop()
+
+ def test_disconnect(self):
+ # after disconnecting from the mqtt server, we should
+ # automatically reconnect
+ self.mqtt.disconnect()
+ time.sleep(2)
+ self.assertTrue(self.mqtt.connected)
+
+ def test_disconnect_and_stay(self):
+ # unless we really want to force a disconnection
+ self.mqtt.disconnect(reconnect=False)
+ time.sleep(2)
+ self.assertFalse(self.mqtt.connected)
+ self.assertFalse(self.mqtt.reconnect)