Commit 9fc93f71 authored by Gezer's avatar Gezer
Browse files

Integration of stream_processing in backend

parent 9bc7c327
Showing with 109 additions and 251 deletions
+109 -251
File moved
...@@ -14,5 +14,5 @@ client = InfluxDBHelper( ...@@ -14,5 +14,5 @@ client = InfluxDBHelper(
tables = client.get_all_data() tables = client.get_all_data()
for table in tables: for table in tables:
for record in table.records: for record in table.records:
print(record) print(record)
\ No newline at end of file
...@@ -32,7 +32,7 @@ def login_view(request): ...@@ -32,7 +32,7 @@ def login_view(request):
user = authenticate(request, username=email, password=password) user = authenticate(request, username=email, password=password)
if user: if user:
login(request, user) # also creates a session in the browser login(request, user) # also creates a session in the browser
return JsonResponse({"success": True}) return JsonResponse({"success": True})
return JsonResponse( return JsonResponse(
{"success": False, "message": "Invalid credentials"}, status=401 {"success": False, "message": "Invalid credentials"}, status=401
...@@ -40,7 +40,7 @@ def login_view(request): ...@@ -40,7 +40,7 @@ def login_view(request):
def logout_view(request): def logout_view(request):
logout(request) logout(request)
return JsonResponse({"message": "Logged out"}) return JsonResponse({"message": "Logged out"})
......
...@@ -4,7 +4,7 @@ version = "0.1.0" ...@@ -4,7 +4,7 @@ version = "0.1.0"
description = "backend of co2 web service" description = "backend of co2 web service"
authors = [ authors = [
{name = "Patrick Ade", email = "21adpa1bif@hft-stuttgart.de"}, {name = "Patrick Ade", email = "21adpa1bif@hft-stuttgart.de"},
{name = "Morten Stetter", email = "22?stmo1bif@hft-stuttgart.de"}, {name = "Morten Stetter", email = "22stmo1bif@hft-stuttgart.de"},
{name = "Aaron Mele", email = "21meaa1bif@hft-stuttgart.de"}, {name = "Aaron Mele", email = "21meaa1bif@hft-stuttgart.de"},
{name = "Emre Gezer", email = "21geem1bif@hft-stuttgart.de"}, {name = "Emre Gezer", email = "21geem1bif@hft-stuttgart.de"},
] ]
...@@ -19,7 +19,8 @@ dependencies = [ ...@@ -19,7 +19,8 @@ dependencies = [
"django>=5.2", "django>=5.2",
"django-cors-headers>=4.7.0", "django-cors-headers>=4.7.0",
"influxdb-client>=1.40", "influxdb-client>=1.40",
"python-dotenv", "python-dotenv>=1.1",
"paho-mqtt>=2.1",
] ]
[dependency-groups] [dependency-groups]
...@@ -34,3 +35,14 @@ line-length = 80 ...@@ -34,3 +35,14 @@ line-length = 80
[tool.ruff.lint] [tool.ruff.lint]
# Add the `line-too-long` rule to the enforced rule set. # Add the `line-too-long` rule to the enforced rule set.
extend-select = ["E501"] extend-select = ["E501"]
#[build-system]
#requires = ["setuptools" ] #"wheel"
#build-backend = "setuptools.build_meta"
#[tool.setuptools]
#package-dir = {"" = "."}
#[tool.setuptools.packages.find]
#where = ["backend"]
from influxdb_client import InfluxDBClient, Point, WritePrecision from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS from influxdb_client.client.write_api import SYNCHRONOUS
class InfluxDBWriter: class InfluxDBWriter:
def __init__(self, url: str, token: str, org: str, bucket: str): def __init__(self, url: str, token: str, org: str, bucket: str):
self.client = InfluxDBClient(url=url, token=token, org=org) self.client = InfluxDBClient(url=url, token=token, org=org)
...@@ -8,7 +9,9 @@ class InfluxDBWriter: ...@@ -8,7 +9,9 @@ class InfluxDBWriter:
self.bucket = bucket self.bucket = bucket
self.org = org self.org = org
def write_point(self, measurement: str, tags: dict, fields: dict, timestamp=None): def write_point(
self, measurement: str, tags: dict, fields: dict, timestamp=None
):
point = Point(measurement) point = Point(measurement)
for k, v in tags.items(): for k, v in tags.items():
point.tag(k, v) point.tag(k, v)
......
import json import json
import os import os
def load_json(file_name: str) -> dict:
def load_json(file_name: str) -> dict:
""" """
ladet eine JSON Datei, wenn diese existiert, ladet eine JSON Datei, wenn diese existiert,
und gibt diese als dictionary zurück und gibt diese als dictionary zurück
key : value key : value
""" """
if not os.path.exists(file_name): if not os.path.exists(file_name):
return {} return {}
...@@ -13,9 +14,10 @@ def load_json(file_name: str) -> dict: ...@@ -13,9 +14,10 @@ def load_json(file_name: str) -> dict:
mac_room_mapping = json.load(f) mac_room_mapping = json.load(f)
return mac_room_mapping return mac_room_mapping
def write_json(mac_room_mapping: dict, file_name: str): def write_json(mac_room_mapping: dict, file_name: str):
""" """
Nimmt ein dictionary und schreibt dessen Nimmt ein dictionary und schreibt dessen
Inhalte in eine JSON Datei Inhalte in eine JSON Datei
""" """
with open(file_name, "w") as f: with open(file_name, "w") as f:
......
import json import json
from mqtt_influx_backend.loggingFactory import LoggerFactory from utils.loggingFactory import LoggerFactory
from datetime import datetime from datetime import datetime
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from mqtt_influx_backend import jsonhandler from stream_processing import jsonhandler
from utils.influx import InfluxDBHelper from utils.influx import InfluxDBHelper
class MQTTClientHandler:
MAPPING_FILE_NAME = "src/mqtt_influx_backend/mac_to_room.json" class MQTTClientHandler:
MAPPING_FILE_NAME = "stream_processing/mac_to_room.json"
MEASUREMENT_NAME = "sensor_data" MEASUREMENT_NAME = "sensor_data"
TAG_ROOM = "room" TAG_ROOM = "room"
TAG_MAC = "mac" TAG_MAC = "mac"
...@@ -17,7 +17,9 @@ class MQTTClientHandler: ...@@ -17,7 +17,9 @@ class MQTTClientHandler:
FIELD_HUMIDITY = "humidity" FIELD_HUMIDITY = "humidity"
# Konstruktor # Konstruktor
def __init__(self, broker_url: str, topic: str, influx_writer: InfluxDBHelper): def __init__(
self, broker_url: str, topic: str, influx_writer: InfluxDBHelper
):
self.logger = LoggerFactory.get_logger(__name__) self.logger = LoggerFactory.get_logger(__name__)
# key: mac : value : room # key: mac : value : room
self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME) self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME)
...@@ -25,58 +27,61 @@ class MQTTClientHandler: ...@@ -25,58 +27,61 @@ class MQTTClientHandler:
self.topic = topic self.topic = topic
self.influx_writer = influx_writer self.influx_writer = influx_writer
self.client = mqtt.Client() self.client = mqtt.Client()
# Methoden werden hier Events zugeteilt # Methoden werden hier Events zugeteilt
self.client.on_connect = self.on_connect self.client.on_connect = self.on_connect
self.client.on_message = self.on_message self.client.on_message = self.on_message
def on_connect(self, client, userdata, flags, rc): def on_connect(self, client, userdata, flags, rc):
self.logger.info("Connected with result code " + str(rc)) self.logger.info("Connected with result code " + str(rc))
client.subscribe(self.topic) client.subscribe(self.topic)
self.logger.info("Subscribed to " + self.topic ) self.logger.info("Subscribed to " + self.topic)
# eventuell refactorn und die Aufgaben in Methoden aufteilen # eventuell refactorn und die Aufgaben in Methoden aufteilen
def on_message(self, client, userdata, msg): def on_message(self, client, userdata, msg):
""" """
Wenn das Topic eine Nachricht bekommt wird diese Methode ausgeführt Wenn das Topic eine Nachricht bekommt wird diese Methode ausgeführt
self: ist die MQTTClientHandler instanz, die wird gebraucht um die Einträge in self: ist die MQTTClientHandler instanz, die wird gebraucht um die Einträge in
die InfluxDB zu schreiben die InfluxDB zu schreiben
""" """
msg = json.loads(msg.payload) msg = json.loads(msg.payload)
metadate = msg["metadata"] metadate = msg["metadata"]
# hier prüfen, ob die Mac-Adresse einen Raum hat, # hier prüfen, ob die Mac-Adresse einen Raum hat,
# wenn nicht trage es in mac_to_room leer ein # wenn nicht trage es in mac_to_room leer ein
# "aa:bb:cc:dd:ee:ff" : "" # "aa:bb:cc:dd:ee:ff" : ""
mac = metadate["mac-address"] mac = metadate["mac-address"]
if mac not in self.mac_to_room: if mac not in self.mac_to_room:
self.logger.warning(f"Neue MAC-Adresse gefunden: {mac}. Mapping wird ergänzt.") self.logger.warning(
f"Neue MAC-Adresse gefunden: {mac}. Mapping wird ergänzt."
)
self.mac_to_room[mac] = "" # leerer Platzhalter self.mac_to_room[mac] = "" # leerer Platzhalter
jsonhandler.write_json(self.mac_to_room, self.MAPPING_FILE_NAME) jsonhandler.write_json(self.mac_to_room, self.MAPPING_FILE_NAME)
self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME) self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME)
return return
self.write_to_influxDB(msg,metadate)
self.write_to_influxDB(msg, metadate)
def write_to_influxDB(self, msg : dict, metadate: dict): def write_to_influxDB(self, msg: dict, metadate: dict):
try: try:
self.influx_writer.write_point( self.influx_writer.write_point(
measurement=self.MEASUREMENT_NAME, measurement=self.MEASUREMENT_NAME,
tags={ tags={
self.TAG_ROOM : self.mac_to_room[metadate["mac-address"]], self.TAG_ROOM: self.mac_to_room[metadate["mac-address"]],
self.TAG_MAC: metadate["mac-address"] self.TAG_MAC: metadate["mac-address"],
}, },
fields={ fields={
self.FIELD_CO2: msg["co2"], self.FIELD_CO2: msg["co2"],
self.FIELD_TEMP: msg["temp"], self.FIELD_TEMP: msg["temp"],
self.FIELD_HUMIDITY: msg["rh"], self.FIELD_HUMIDITY: msg["rh"],
}, },
timestamp=metadate["time"], #fix timestamp=metadate["time"], # fix
) )
print("Wrote to InfluxDB:", msg) # muss später rausgeschmiessen werden print(
"Wrote to InfluxDB:", msg
) # muss später rausgeschmiessen werden
except Exception as e: except Exception as e:
self.logger.error(f"Failed writing to InfluxDb: {e}") self.logger.error(f"Failed writing to InfluxDb: {e}")
def start(self): def start(self):
self.client.connect(self.broker_url) self.client.connect(self.broker_url)
......
...@@ -8,5 +8,7 @@ ...@@ -8,5 +8,7 @@
"lK:AD:BE:EF:12:34": "", "lK:AD:BE:EF:12:34": "",
"MK:AD:BE:EF:12:34": "", "MK:AD:BE:EF:12:34": "",
"AB:AD:BE:EF:12:34": "", "AB:AD:BE:EF:12:34": "",
"EF:AD:BE:EF:12:34": "" "EF:AD:BE:EF:12:34": "",
"Tx:AD:BE:EF:12:34": "",
"T\u00dc:AD:BE:EF:12:34": ""
} }
\ No newline at end of file
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
from mqtt_influx_backend.mQTTClientHandler import MQTTClientHandler from stream_processing.mQTTClientHandler import MQTTClientHandler
from utils.influx import InfluxDBHelper from utils.influx import InfluxDBHelper
load_dotenv() load_dotenv()
def main():
def main():
influx_writer = InfluxDBHelper( influx_writer = InfluxDBHelper(
url=os.getenv("INFLUXDB_URL"), url=os.getenv("INFLUXDB_URL"),
token=os.getenv("INFLUXDB_TOKEN"), token=os.getenv("INFLUXDB_TOKEN"),
......
...@@ -2,6 +2,7 @@ import os ...@@ -2,6 +2,7 @@ import os
from influxdb_client import InfluxDBClient, Point, WritePrecision from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import WriteOptions from influxdb_client.client.write_api import WriteOptions
class InfluxDBHelper: class InfluxDBHelper:
def __init__(self, url: str, token: str, org: str, bucket: str): def __init__(self, url: str, token: str, org: str, bucket: str):
self.client = InfluxDBClient(url=url, token=token, org=org) self.client = InfluxDBClient(url=url, token=token, org=org)
...@@ -9,12 +10,14 @@ class InfluxDBHelper: ...@@ -9,12 +10,14 @@ class InfluxDBHelper:
self.org = org self.org = org
self.query_api = self.client.query_api() self.query_api = self.client.query_api()
# self.write_api = self.client.write_api(write_options=SYNCHRONOUS) good for debug # self.write_api = self.client.write_api(write_options=SYNCHRONOUS) good for debug
self.write_api = self.client.write_api(write_options=WriteOptions(batch_size=1000, flush_interval=10000)) self.write_api = self.client.write_api(
write_options=WriteOptions(batch_size=1000, flush_interval=10000)
)
def write_point(self, measurement: str, tags: dict, fields: dict, timestamp=None): def write_point(
''' self, measurement: str, tags: dict, fields: dict, timestamp=None
):
''' """ """
point = Point(measurement) point = Point(measurement)
for k, v in tags.items(): for k, v in tags.items():
point.tag(k, v) point.tag(k, v)
...@@ -25,8 +28,7 @@ class InfluxDBHelper: ...@@ -25,8 +28,7 @@ class InfluxDBHelper:
self.write_api.write(bucket=self.bucket, org=self.org, record=point) self.write_api.write(bucket=self.bucket, org=self.org, record=point)
def get_all_data(self): def get_all_data(self):
''' """ """
'''
query = f''' query = f'''
from(bucket: "{self.bucket}") from(bucket: "{self.bucket}")
|> range(start: -20d) |> range(start: -20d)
...@@ -35,8 +37,7 @@ class InfluxDBHelper: ...@@ -35,8 +37,7 @@ class InfluxDBHelper:
return self.query_api.query(org=self.org, query=query) return self.query_api.query(org=self.org, query=query)
def get_latest_room_data(self, room_id: str): def get_latest_room_data(self, room_id: str):
''' """ """
'''
query = f''' query = f'''
from(bucket: "{self.bucket}") from(bucket: "{self.bucket}")
|> range(start: -5m) |> range(start: -5m)
......
File moved
...@@ -6,11 +6,11 @@ LOG_DIR = "logs" ...@@ -6,11 +6,11 @@ LOG_DIR = "logs"
LOG_FILE = "app.log" LOG_FILE = "app.log"
LOG_PATH = os.path.join(LOG_DIR, LOG_FILE) LOG_PATH = os.path.join(LOG_DIR, LOG_FILE)
class LoggerFactory:
#logger.info("Connected with result code %s", str(rc)) class LoggerFactory:
#logger.warning("Neue MAC-Adresse gefunden: %s", mac) # logger.info("Connected with result code %s", str(rc))
#logger.error("Failed writing to InfluxDb: %s", e) # logger.warning("Neue MAC-Adresse gefunden: %s", mac)
# logger.error("Failed writing to InfluxDb: %s", e)
@staticmethod @staticmethod
def get_logger(name: str, level=logging.DEBUG) -> logging.Logger: def get_logger(name: str, level=logging.DEBUG) -> logging.Logger:
...@@ -24,11 +24,13 @@ class LoggerFactory: ...@@ -24,11 +24,13 @@ class LoggerFactory:
logger.setLevel(level) logger.setLevel(level)
formatter = logging.Formatter( formatter = logging.Formatter(
'[%(asctime)s] %(levelname)s in %(name)s: %(message)s', "[%(asctime)s] %(levelname)s in %(name)s: %(message)s",
datefmt='%Y-%m-%d %H:%M:%S' datefmt="%Y-%m-%d %H:%M:%S",
) )
file_handler = RotatingFileHandler(LOG_PATH, maxBytes=5_000_000, backupCount=5) file_handler = RotatingFileHandler(
LOG_PATH, maxBytes=5_000_000, backupCount=5
)
file_handler.setFormatter(formatter) file_handler.setFormatter(formatter)
logger.addHandler(file_handler) logger.addHandler(file_handler)
......
...@@ -19,6 +19,7 @@ dependencies = [ ...@@ -19,6 +19,7 @@ dependencies = [
{ name = "django" }, { name = "django" },
{ name = "django-cors-headers" }, { name = "django-cors-headers" },
{ name = "influxdb-client" }, { name = "influxdb-client" },
{ name = "paho-mqtt" },
{ name = "python-dotenv" }, { name = "python-dotenv" },
] ]
...@@ -32,7 +33,8 @@ requires-dist = [ ...@@ -32,7 +33,8 @@ requires-dist = [
{ name = "django", specifier = ">=5.2" }, { name = "django", specifier = ">=5.2" },
{ name = "django-cors-headers", specifier = ">=4.7.0" }, { name = "django-cors-headers", specifier = ">=4.7.0" },
{ name = "influxdb-client", specifier = ">=1.40" }, { name = "influxdb-client", specifier = ">=1.40" },
{ name = "python-dotenv" }, { name = "paho-mqtt", specifier = ">=2.1" },
{ name = "python-dotenv", specifier = ">=1.1" },
] ]
[package.metadata.requires-dev] [package.metadata.requires-dev]
...@@ -90,6 +92,15 @@ wheels = [ ...@@ -90,6 +92,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/b3/1edc89584b8d1bc5226cf508b67ab64da3ba83041cab348861e6f4392326/influxdb_client-1.48.0-py3-none-any.whl", hash = "sha256:410db15db761df7ea98adb333c7a03f05bcc2ceef4830cefb7071b888be2b827", size = 746177 }, { url = "https://files.pythonhosted.org/packages/5c/b3/1edc89584b8d1bc5226cf508b67ab64da3ba83041cab348861e6f4392326/influxdb_client-1.48.0-py3-none-any.whl", hash = "sha256:410db15db761df7ea98adb333c7a03f05bcc2ceef4830cefb7071b888be2b827", size = 746177 },
] ]
[[package]]
name = "paho-mqtt"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/39/15/0a6214e76d4d32e7f663b109cf71fb22561c2be0f701d67f93950cd40542/paho_mqtt-2.1.0.tar.gz", hash = "sha256:12d6e7511d4137555a3f6ea167ae846af2c7357b10bc6fa4f7c3968fc1723834", size = 148848 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219 },
]
[[package]] [[package]]
name = "python-dateutil" name = "python-dateutil"
version = "2.9.0.post0" version = "2.9.0.post0"
...@@ -125,27 +136,27 @@ wheels = [ ...@@ -125,27 +136,27 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.11.5" version = "0.11.6"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/45/71/5759b2a6b2279bb77fe15b1435b89473631c2cd6374d45ccdb6b785810be/ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef", size = 3976488 } sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/23/db/6efda6381778eec7f35875b5cbefd194904832a1153d68d36d6b269d81a8/ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b", size = 10103150 }, { url = "https://files.pythonhosted.org/packages/6e/1f/8848b625100ebcc8740c8bac5b5dd8ba97dd4ee210970e98832092c1635b/ruff-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:d84dcbe74cf9356d1bdb4a78cf74fd47c740bf7bdeb7529068f69b08272239a1", size = 10248105 },
{ url = "https://files.pythonhosted.org/packages/44/f2/06cd9006077a8db61956768bc200a8e52515bf33a8f9b671ee527bb10d77/ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077", size = 10898637 }, { url = "https://files.pythonhosted.org/packages/e0/47/c44036e70c6cc11e6ee24399c2a1e1f1e99be5152bd7dff0190e4b325b76/ruff-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9bc583628e1096148011a5d51ff3c836f51899e61112e03e5f2b1573a9b726de", size = 11001494 },
{ url = "https://files.pythonhosted.org/packages/18/f5/af390a013c56022fe6f72b95c86eb7b2585c89cc25d63882d3bfe411ecf1/ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779", size = 10236012 }, { url = "https://files.pythonhosted.org/packages/ed/5b/170444061650202d84d316e8f112de02d092bff71fafe060d3542f5bc5df/ruff-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2959049faeb5ba5e3b378709e9d1bf0cab06528b306b9dd6ebd2a312127964a", size = 10352151 },
{ url = "https://files.pythonhosted.org/packages/b8/ca/b9bf954cfed165e1a0c24b86305d5c8ea75def256707f2448439ac5e0d8b/ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794", size = 10415338 }, { url = "https://files.pythonhosted.org/packages/ff/91/f02839fb3787c678e112c8865f2c3e87cfe1744dcc96ff9fc56cfb97dda2/ruff-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c5d4e30d9d0de7fedbfb3e9e20d134b73a30c1e74b596f40f0629d5c28a193", size = 10541951 },
{ url = "https://files.pythonhosted.org/packages/d9/4d/2522dde4e790f1b59885283f8786ab0046958dfd39959c81acc75d347467/ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038", size = 9965277 }, { url = "https://files.pythonhosted.org/packages/9e/f3/c09933306096ff7a08abede3cc2534d6fcf5529ccd26504c16bf363989b5/ruff-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4b9a4e1439f7d0a091c6763a100cef8fbdc10d68593df6f3cfa5abdd9246e", size = 10079195 },
{ url = "https://files.pythonhosted.org/packages/e5/7a/749f56f150eef71ce2f626a2f6988446c620af2f9ba2a7804295ca450397/ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f", size = 11541614 }, { url = "https://files.pythonhosted.org/packages/e0/0d/a87f8933fccbc0d8c653cfbf44bedda69c9582ba09210a309c066794e2ee/ruff-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5edf270223dd622218256569636dc3e708c2cb989242262fe378609eccf1308", size = 11698918 },
{ url = "https://files.pythonhosted.org/packages/89/b2/7d9b8435222485b6aac627d9c29793ba89be40b5de11584ca604b829e960/ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82", size = 12198873 }, { url = "https://files.pythonhosted.org/packages/52/7d/8eac0bd083ea8a0b55b7e4628428203441ca68cd55e0b67c135a4bc6e309/ruff-0.11.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f55844e818206a9dd31ff27f91385afb538067e2dc0beb05f82c293ab84f7d55", size = 12319426 },
{ url = "https://files.pythonhosted.org/packages/00/e0/a1a69ef5ffb5c5f9c31554b27e030a9c468fc6f57055886d27d316dfbabd/ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304", size = 11670190 }, { url = "https://files.pythonhosted.org/packages/c2/dc/d0c17d875662d0c86fadcf4ca014ab2001f867621b793d5d7eef01b9dcce/ruff-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d8f782286c5ff562e4e00344f954b9320026d8e3fae2ba9e6948443fafd9ffc", size = 11791012 },
{ url = "https://files.pythonhosted.org/packages/05/61/c1c16df6e92975072c07f8b20dad35cd858e8462b8865bc856fe5d6ccb63/ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470", size = 13902301 }, { url = "https://files.pythonhosted.org/packages/f9/f3/81a1aea17f1065449a72509fc7ccc3659cf93148b136ff2a8291c4bc3ef1/ruff-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01c63ba219514271cee955cd0adc26a4083df1956d57847978383b0e50ffd7d2", size = 13949947 },
{ url = "https://files.pythonhosted.org/packages/79/89/0af10c8af4363304fd8cb833bd407a2850c760b71edf742c18d5a87bb3ad/ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a", size = 11350132 }, { url = "https://files.pythonhosted.org/packages/61/9f/a3e34de425a668284e7024ee6fd41f452f6fa9d817f1f3495b46e5e3a407/ruff-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15adac20ef2ca296dd3d8e2bedc6202ea6de81c091a74661c3666e5c4c223ff6", size = 11471753 },
{ url = "https://files.pythonhosted.org/packages/b9/e1/ecb4c687cbf15164dd00e38cf62cbab238cad05dd8b6b0fc68b0c2785e15/ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b", size = 10312937 }, { url = "https://files.pythonhosted.org/packages/df/c5/4a57a86d12542c0f6e2744f262257b2aa5a3783098ec14e40f3e4b3a354a/ruff-0.11.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4dd6b09e98144ad7aec026f5588e493c65057d1b387dd937d7787baa531d9bc2", size = 10417121 },
{ url = "https://files.pythonhosted.org/packages/cf/4f/0e53fe5e500b65934500949361e3cd290c5ba60f0324ed59d15f46479c06/ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a", size = 9936683 }, { url = "https://files.pythonhosted.org/packages/58/3f/a3b4346dff07ef5b862e2ba06d98fcbf71f66f04cf01d375e871382b5e4b/ruff-0.11.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:45b2e1d6c0eed89c248d024ea95074d0e09988d8e7b1dad8d3ab9a67017a5b03", size = 10073829 },
{ url = "https://files.pythonhosted.org/packages/04/a8/8183c4da6d35794ae7f76f96261ef5960853cd3f899c2671961f97a27d8e/ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159", size = 10950217 }, { url = "https://files.pythonhosted.org/packages/93/cc/7ed02e0b86a649216b845b3ac66ed55d8aa86f5898c5f1691797f408fcb9/ruff-0.11.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd40de4115b2ec4850302f1a1d8067f42e70b4990b68838ccb9ccd9f110c5e8b", size = 11076108 },
{ url = "https://files.pythonhosted.org/packages/26/88/9b85a5a8af21e46a0639b107fcf9bfc31da4f1d263f2fc7fbe7199b47f0a/ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783", size = 11404521 }, { url = "https://files.pythonhosted.org/packages/39/5e/5b09840fef0eff1a6fa1dea6296c07d09c17cb6fb94ed5593aa591b50460/ruff-0.11.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:77cda2dfbac1ab73aef5e514c4cbfc4ec1fbef4b84a44c736cc26f61b3814cd9", size = 11512366 },
{ url = "https://files.pythonhosted.org/packages/fc/52/047f35d3b20fd1ae9ccfe28791ef0f3ca0ef0b3e6c1a58badd97d450131b/ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe", size = 10320697 }, { url = "https://files.pythonhosted.org/packages/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900 },
{ url = "https://files.pythonhosted.org/packages/b9/fe/00c78010e3332a6e92762424cf4c1919065707e962232797d0b57fd8267e/ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800", size = 11378665 }, { url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592 },
{ url = "https://files.pythonhosted.org/packages/43/7c/c83fe5cbb70ff017612ff36654edfebec4b1ef79b558b8e5fd933bab836b/ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e", size = 10460287 }, { url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 },
] ]
[[package]] [[package]]
......
FROM python:3.12-slim
# Arbeitsverzeichnis im Container
WORKDIR /app
# Projektdateien kopieren
COPY . .
# uv installieren
RUN pip install uv
# Installiere Abhängigkeiten aus pyproject.toml
RUN uv pip install . --no-cache-dir --system
# Startkommando
CMD ["uv", "run", "-m", "mqtt_influx_backend.main"]
mosquitto_pub -h 172.20.10.12 -t co2/esp32 -m "{
"metadata": {
"timestamp": "2025-04-12T14:22:35Z",
"mac": "AA:BB:CC:DD:EE:FF",
"room": "A123"
},
"co2": 615.3,
"temperature": 21.8,
"humidity": 45.2
}"
[project]
name = "mqtt-influx-backend"
version = "0.1.0"
description = "Backend to write MQTT sensor data to InfluxDB"
readme = "README.md"
authors = [
{name = "Patrick Ade", email = "21adpa1bif@hft-stuttgart.de"},
{name = "Morten Stetter", email = "22?stmo1bif@hft-stuttgart.de"},
{name = "Aaron Mele", email = "21meaa1bif@hft-stuttgart.de"},
{name = "Emre Gezer", email = "21geem1bif@hft-stuttgart.de"},
]
maintainers = [
{name = "Max Mustermann", email = "mustermann@example.com"}
]
keywords = ["co2", "sensor", "temperature", "humidity", "monitor", "monitoring", "air quality"]
requires-python = ">=3.10"
dependencies = [
"paho-mqtt",
"influxdb-client",
"python-dotenv",
]
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]
version = 1
revision = 1
requires-python = ">=3.10"
[[package]]
name = "certifi"
version = "2025.1.31"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
]
[[package]]
name = "influxdb-client"
version = "1.48.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "python-dateutil" },
{ name = "reactivex" },
{ name = "setuptools" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/11/47/b756380917cb4b968bd871fc006128e2cc9897fb1ab4bcf7d108f9601e78/influxdb_client-1.48.0.tar.gz", hash = "sha256:414d5b5eff7d2b6b453f33e2826ea9872ea04a11996ba9c8604b0c1df57c8559", size = 386415 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/b3/1edc89584b8d1bc5226cf508b67ab64da3ba83041cab348861e6f4392326/influxdb_client-1.48.0-py3-none-any.whl", hash = "sha256:410db15db761df7ea98adb333c7a03f05bcc2ceef4830cefb7071b888be2b827", size = 746177 },
]
[[package]]
name = "mqtt-influx-backend"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "influxdb-client" },
{ name = "paho-mqtt" },
{ name = "python-dotenv" },
]
[package.metadata]
requires-dist = [
{ name = "influxdb-client" },
{ name = "paho-mqtt" },
{ name = "python-dotenv" },
]
[[package]]
name = "paho-mqtt"
version = "2.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/39/15/0a6214e76d4d32e7f663b109cf71fb22561c2be0f701d67f93950cd40542/paho_mqtt-2.1.0.tar.gz", hash = "sha256:12d6e7511d4137555a3f6ea167ae846af2c7357b10bc6fa4f7c3968fc1723834", size = 148848 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219 },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
]
[[package]]
name = "python-dotenv"
version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 },
]
[[package]]
name = "reactivex"
version = "4.0.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ef/63/f776322df4d7b456446eff78c4e64f14c3c26d57d46b4e06c18807d5d99c/reactivex-4.0.4.tar.gz", hash = "sha256:e912e6591022ab9176df8348a653fe8c8fa7a301f26f9931c9d8c78a650e04e8", size = 119177 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/3f/2ed8c1b8fe3fc2ed816ba40554ef703aad8c51700e2606c139fcf9b7f791/reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a", size = 217791 },
]
[[package]]
name = "setuptools"
version = "78.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a9/5a/0db4da3bc908df06e5efae42b44e75c81dd52716e10192ff36d0c1c8e379/setuptools-78.1.0.tar.gz", hash = "sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54", size = 1367827 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/21/f43f0a1fa8b06b32812e0975981f4677d28e0f3271601dc88ac5a5b83220/setuptools-78.1.0-py3-none-any.whl", hash = "sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8", size = 1256108 },
]
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
]
[[package]]
name = "typing-extensions"
version = "4.13.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 },
]
[[package]]
name = "urllib3"
version = "2.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 },
]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment