From d22cb38ddedbbf98c62b9e79eabed4f0e71bda9b Mon Sep 17 00:00:00 2001 From: IP2_Mele <21meaa1bif@hft-stuttgart.de> Date: Tue, 20 May 2025 14:41:39 +0200 Subject: [PATCH] small chanches to everything ^^ --- backend/.env.docker | 2 +- backend/Dockerfile | 4 +- backend/stream_processing/jsonhandler.py | 24 ---- backend/uv.lock | 110 +++++++++--------- docker-compose.yaml | 14 ++- ordnerstruktur.txt | Bin 0 -> 1097692 bytes services/influxdb/influxdb2-admin-password | 2 +- services/influxdb/influxdb2-admin-token | 2 +- services/influxdb/influxdb2-admin-username | 2 +- .../Dockerfile | 10 +- .../__init__.py | 0 stream_processing/jsonhandler.py | 27 +++++ .../mQTTClientHandler.py | 11 +- .../mac_to_room.json | 4 +- .../main.py | 11 +- stream_processing/pyproject.toml | 46 ++++++++ stream_processing/utils/__init__.py | 0 stream_processing/utils/fluxQueryBuilder.py | 103 ++++++++++++++++ stream_processing/utils/influx.py | 52 +++++++++ stream_processing/utils/init.py | 0 stream_processing/utils/loggingFactory.py | 37 ++++++ 21 files changed, 362 insertions(+), 99 deletions(-) delete mode 100644 backend/stream_processing/jsonhandler.py create mode 100644 ordnerstruktur.txt rename {backend/stream_processing => stream_processing}/Dockerfile (79%) rename {backend/stream_processing => stream_processing}/__init__.py (100%) create mode 100644 stream_processing/jsonhandler.py rename {backend/stream_processing => stream_processing}/mQTTClientHandler.py (93%) rename {backend/stream_processing => stream_processing}/mac_to_room.json (91%) rename {backend/stream_processing => stream_processing}/main.py (62%) create mode 100644 stream_processing/pyproject.toml create mode 100644 stream_processing/utils/__init__.py create mode 100644 stream_processing/utils/fluxQueryBuilder.py create mode 100644 stream_processing/utils/influx.py create mode 100644 stream_processing/utils/init.py create mode 100644 stream_processing/utils/loggingFactory.py diff --git a/backend/.env.docker b/backend/.env.docker index 0d29546..5f01a49 100644 --- a/backend/.env.docker +++ b/backend/.env.docker @@ -2,7 +2,7 @@ INFLUXDB_URL=http://influxdb2:8086 INFLUXDB_ORG=docs INFLUXDB_BUCKET=co2-test -INFLUXDB_TOKEN=w-Isk1D35T90Srj_auFTxsbksn1zRB5MiNZf6h6RuNdb9-2s9ie5c1488JqoYILKrceVm0LaE5KCN2dXdDM-jA== +INFLUXDB_TOKEN=1xa5lLACRZDYsvinhABndZ8GGzBY7-gTQsAf309c0aTnPPtBxixPEEOPuXLmkTxUKy8golKae6fsrh1wD4SL0A== # MQTT config MQTT_BROKER_URL=mosquitto-broker MQTT_TOPIC="co2/#" \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile index f0116b8..9851bc8 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -5,7 +5,7 @@ FROM python:latest WORKDIR /app # Kopiere Projektdateien für Abhängigkeitsmanagement -COPY pyproject.toml uv.lock ./ +COPY . . # Installiere pip und uv RUN pip install --upgrade pip && \ @@ -21,7 +21,7 @@ RUN uv sync # für Admin oberfläche #RUN python manage.py createsuperuser -COPY . . +#COPY . . RUN .venv/bin/python manage.py migrate diff --git a/backend/stream_processing/jsonhandler.py b/backend/stream_processing/jsonhandler.py deleted file mode 100644 index d90ba36..0000000 --- a/backend/stream_processing/jsonhandler.py +++ /dev/null @@ -1,24 +0,0 @@ -import json -import os - -def load_json(file_name: str) -> dict: - """ - ladet eine JSON Datei, wenn diese existiert, - und gibt diese als dictionary zurück - key : value - """ - if not os.path.exists(file_name): - return {} - with open(file_name) as f: - mac_room_mapping = json.load(f) - return mac_room_mapping - -def write_json(mac_room_mapping: dict, file_name: str): - """ - Nimmt ein dictionary und schreibt dessen - Inhalte in eine JSON Datei - """ - with open(file_name, "w") as f: - f.seek(0) - json.dump(mac_room_mapping, f, indent=4) - f.truncate() # TODO Check if truncate is necessary? diff --git a/backend/uv.lock b/backend/uv.lock index 497e2a0..e9aa3ae 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -1,14 +1,14 @@ version = 1 -revision = 1 +revision = 2 requires-python = ">=3.12" [[package]] name = "asgiref" version = "3.8.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186 } +sdist = { url = "https://files.pythonhosted.org/packages/29/38/b3395cc9ad1b56d2ddac9970bc8f4141312dbaec28bc7c218b0dfafd0f42/asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590", size = 35186, upload-time = "2024-03-22T14:39:36.863Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828 }, + { url = "https://files.pythonhosted.org/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", size = 23828, upload-time = "2024-03-22T14:39:34.521Z" }, ] [[package]] @@ -42,25 +42,25 @@ dev = [{ name = "ruff", specifier = ">=0.11.5" }] [[package]] name = "certifi" -version = "2025.1.31" +version = "2025.4.26" 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 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, ] [[package]] name = "django" -version = "5.2" +version = "5.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asgiref" }, { name = "sqlparse" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/1b/c6da718c65228eb3a7ff7ba6a32d8e80fa840ca9057490504e099e4dd1ef/Django-5.2.tar.gz", hash = "sha256:1a47f7a7a3d43ce64570d350e008d2949abe8c7e21737b351b6a1611277c6d89", size = 10824891 } +sdist = { url = "https://files.pythonhosted.org/packages/ac/10/0d546258772b8f31398e67c85e52c66ebc2b13a647193c3eef8ee433f1a8/django-5.2.1.tar.gz", hash = "sha256:57fe1f1b59462caed092c80b3dd324fd92161b620d59a9ba9181c34746c97284", size = 10818735, upload-time = "2025-05-07T14:06:17.543Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/e0/6a5b5ea350c5bd63fe94b05e4c146c18facb51229d9dee42aa39f9fc2214/Django-5.2-py3-none-any.whl", hash = "sha256:91ceed4e3a6db5aedced65e3c8f963118ea9ba753fc620831c77074e620e7d83", size = 8301361 }, + { url = "https://files.pythonhosted.org/packages/90/92/7448697b5838b3a1c6e1d2d6a673e908d0398e84dc4f803a2ce11e7ffc0f/django-5.2.1-py3-none-any.whl", hash = "sha256:a9b680e84f9a0e71da83e399f1e922e1ab37b2173ced046b541c72e1589a5961", size = 8301833, upload-time = "2025-05-07T14:06:10.955Z" }, ] [[package]] @@ -71,9 +71,9 @@ dependencies = [ { name = "asgiref" }, { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/6c/16f6cb6064c63074fd5b2bd494eb319afd846236d9c1a6c765946df2c289/django_cors_headers-4.7.0.tar.gz", hash = "sha256:6fdf31bf9c6d6448ba09ef57157db2268d515d94fc5c89a0a1028e1fc03ee52b", size = 21037 } +sdist = { url = "https://files.pythonhosted.org/packages/93/6c/16f6cb6064c63074fd5b2bd494eb319afd846236d9c1a6c765946df2c289/django_cors_headers-4.7.0.tar.gz", hash = "sha256:6fdf31bf9c6d6448ba09ef57157db2268d515d94fc5c89a0a1028e1fc03ee52b", size = 21037, upload-time = "2025-02-06T22:15:28.924Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/a2/7bcfff86314bd9dd698180e31ba00604001606efb518a06cca6833a54285/django_cors_headers-4.7.0-py3-none-any.whl", hash = "sha256:f1c125dcd58479fe7a67fe2499c16ee38b81b397463cf025f0e2c42937421070", size = 12794 }, + { url = "https://files.pythonhosted.org/packages/7e/a2/7bcfff86314bd9dd698180e31ba00604001606efb518a06cca6833a54285/django_cors_headers-4.7.0-py3-none-any.whl", hash = "sha256:f1c125dcd58479fe7a67fe2499c16ee38b81b397463cf025f0e2c42937421070", size = 12794, upload-time = "2025-02-06T22:15:24.341Z" }, ] [[package]] @@ -87,18 +87,18 @@ dependencies = [ { 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 } +sdist = { url = "https://files.pythonhosted.org/packages/11/47/b756380917cb4b968bd871fc006128e2cc9897fb1ab4bcf7d108f9601e78/influxdb_client-1.48.0.tar.gz", hash = "sha256:414d5b5eff7d2b6b453f33e2826ea9872ea04a11996ba9c8604b0c1df57c8559", size = 386415, upload-time = "2024-11-27T08:26:32.909Z" } 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, upload-time = "2024-11-27T08:26:30.438Z" }, ] [[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 } +sdist = { url = "https://files.pythonhosted.org/packages/39/15/0a6214e76d4d32e7f663b109cf71fb22561c2be0f701d67f93950cd40542/paho_mqtt-2.1.0.tar.gz", hash = "sha256:12d6e7511d4137555a3f6ea167ae846af2c7357b10bc6fa4f7c3968fc1723834", size = 148848, upload-time = "2024-04-29T19:52:55.591Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219 }, + { url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219, upload-time = "2024-04-29T19:52:48.345Z" }, ] [[package]] @@ -108,18 +108,18 @@ 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 } +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } 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 }, + { 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, upload-time = "2024-03-01T18:36:18.57Z" }, ] [[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 } +sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 }, + { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" }, ] [[package]] @@ -129,86 +129,86 @@ 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 } +sdist = { url = "https://files.pythonhosted.org/packages/ef/63/f776322df4d7b456446eff78c4e64f14c3c26d57d46b4e06c18807d5d99c/reactivex-4.0.4.tar.gz", hash = "sha256:e912e6591022ab9176df8348a653fe8c8fa7a301f26f9931c9d8c78a650e04e8", size = 119177, upload-time = "2022-07-16T07:11:53.689Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/3f/2ed8c1b8fe3fc2ed816ba40554ef703aad8c51700e2606c139fcf9b7f791/reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a", size = 217791 }, + { url = "https://files.pythonhosted.org/packages/69/3f/2ed8c1b8fe3fc2ed816ba40554ef703aad8c51700e2606c139fcf9b7f791/reactivex-4.0.4-py3-none-any.whl", hash = "sha256:0004796c420bd9e68aad8e65627d85a8e13f293de76656165dffbcb3a0e3fb6a", size = 217791, upload-time = "2022-07-16T07:11:52.061Z" }, ] [[package]] name = "ruff" -version = "0.11.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053 } -wheels = [ - { 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/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/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/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/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/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/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/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/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/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/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/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/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/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/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900 }, - { 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/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 }, +version = "0.11.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, + { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, + { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, + { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, + { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, + { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, + { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, + { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, + { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, + { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, + { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, + { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, + { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, ] [[package]] name = "setuptools" -version = "79.0.0" +version = "80.7.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/19/fecb7e2825616270f34512b3394cdcf6f45a79b5b6d94fdbd86a509e67b5/setuptools-79.0.0.tar.gz", hash = "sha256:9828422e7541213b0aacb6e10bbf9dd8febeaa45a48570e09b6d100e063fc9f9", size = 1367685 } +sdist = { url = "https://files.pythonhosted.org/packages/9e/8b/dc1773e8e5d07fd27c1632c45c1de856ac3dbf09c0147f782ca6d990cf15/setuptools-80.7.1.tar.gz", hash = "sha256:f6ffc5f0142b1bd8d0ca94ee91b30c0ca862ffd50826da1ea85258a06fd94552", size = 1319188, upload-time = "2025-05-15T02:41:00.955Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/ea/d53f2f8897c46a36df085964d07761ea4c2d1f2cf92019693b6742b7aabb/setuptools-79.0.0-py3-none-any.whl", hash = "sha256:b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a", size = 1256065 }, + { url = "https://files.pythonhosted.org/packages/a1/18/0e835c3a557dc5faffc8f91092f62fc337c1dab1066715842e7a4b318ec4/setuptools-80.7.1-py3-none-any.whl", hash = "sha256:ca5cc1069b85dc23070a6628e6bcecb3292acac802399c7f8edc0100619f9009", size = 1200776, upload-time = "2025-05-15T02:40:58.887Z" }, ] [[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 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] name = "sqlparse" version = "0.5.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999 } +sdist = { url = "https://files.pythonhosted.org/packages/e5/40/edede8dd6977b0d3da179a342c198ed100dd2aba4be081861ee5911e4da4/sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272", size = 84999, upload-time = "2024-12-10T12:05:30.728Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415 }, + { url = "https://files.pythonhosted.org/packages/a9/5c/bfd6bd0bf979426d405cc6e71eceb8701b148b16c21d2dc3c261efc61c7b/sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca", size = 44415, upload-time = "2024-12-10T12:05:27.824Z" }, ] [[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 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 }, + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, ] [[package]] name = "tzdata" version = "2025.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 }, + { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, ] [[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 } +sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 }, + { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, ] diff --git a/docker-compose.yaml b/docker-compose.yaml index eac4c3c..a31683d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,14 +1,14 @@ -services: +services: stream-processing: build: - context: ./backend - dockerfile: stream_processing/Dockerfile + context: ./stream_processing + dockerfile: Dockerfile image: stream-processing container_name: stream-processing volumes: - - ./backend/stream_processing:/app/backend/stream_processing + - ./stream_processing/mac_to_room.json:/app/mac_to_room.json env_file: - ./backend/.env.docker restart: unless-stopped @@ -30,7 +30,9 @@ services: - ./backend:/app frontend: - build: ./frontend + build: + context: ./frontend + dockerfile: Dockerfile ports: - "5173:5173" volumes: @@ -60,7 +62,7 @@ services: ports: - "8081:80" # Port 80 im Container auf 8081 lokal mappen restart: unless-stopped - + influxdb2: image: influxdb:2 ports: diff --git a/ordnerstruktur.txt b/ordnerstruktur.txt new file mode 100644 index 0000000000000000000000000000000000000000..5f44b9a64699799e9779974f474081db9c072d6b GIT binary patch literal 1097692 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 literal 0 HcmV?d00001 diff --git a/services/influxdb/influxdb2-admin-password b/services/influxdb/influxdb2-admin-password index f3097ab..7aa311a 100644 --- a/services/influxdb/influxdb2-admin-password +++ b/services/influxdb/influxdb2-admin-password @@ -1 +1 @@ -password +password \ No newline at end of file diff --git a/services/influxdb/influxdb2-admin-token b/services/influxdb/influxdb2-admin-token index 6f3eee4..e14dde2 100644 --- a/services/influxdb/influxdb2-admin-token +++ b/services/influxdb/influxdb2-admin-token @@ -1 +1 @@ -w-Isk1D35T90Srj_auFTxsbksn1zRB5MiNZf6h6RuNdb9-2s9ie5c1488JqoYILKrceVm0LaE5KCN2dXdDM-jA== \ No newline at end of file +1xa5lLACRZDYsvinhABndZ8GGzBY7-gTQsAf309c0aTnPPtBxixPEEOPuXLmkTxUKy8golKae6fsrh1wD4SL0A== \ No newline at end of file diff --git a/services/influxdb/influxdb2-admin-username b/services/influxdb/influxdb2-admin-username index 7fbe952..f77b004 100644 --- a/services/influxdb/influxdb2-admin-username +++ b/services/influxdb/influxdb2-admin-username @@ -1 +1 @@ -admin +admin \ No newline at end of file diff --git a/backend/stream_processing/Dockerfile b/stream_processing/Dockerfile similarity index 79% rename from backend/stream_processing/Dockerfile rename to stream_processing/Dockerfile index 9849897..92ee137 100644 --- a/backend/stream_processing/Dockerfile +++ b/stream_processing/Dockerfile @@ -1,11 +1,10 @@ -# Verwende das neueste Python-Image FROM python:latest # Setze das Arbeitsverzeichnis im Container WORKDIR /app # Kopiere die pyproject.toml und uv.lock aus dem Backend-Hauptverzeichnis -COPY ../pyproject.toml ../uv.lock ./ +COPY . . # Installiere pip und uv RUN pip install --upgrade pip && \ @@ -19,13 +18,14 @@ RUN uv venv .venv && \ RUN uv sync # Kopiere NUR den Stream-Processing-Code -COPY . . +#COPY . . # Optional: Kopiere ggf. auch andere Module aus dem Backend, falls du darauf zugreifen willst -COPY ../utils ../utils +#COPY utils utils # Setze Umgebungsvariablen ENV PYTHONUNBUFFERED=1 # Startbefehl für das Stream-Processing -CMD ["uv", "run", "python", "-m", "backend.stream_processing.main"] +CMD ["uv", "run", "python", "-m", "main"] + diff --git a/backend/stream_processing/__init__.py b/stream_processing/__init__.py similarity index 100% rename from backend/stream_processing/__init__.py rename to stream_processing/__init__.py diff --git a/stream_processing/jsonhandler.py b/stream_processing/jsonhandler.py new file mode 100644 index 0000000..a6d1126 --- /dev/null +++ b/stream_processing/jsonhandler.py @@ -0,0 +1,27 @@ +import json +import os + +def load_json(file_name: str) -> dict: + """ + ladet eine JSON Datei, wenn diese existiert, + und gibt diese als dictionary zurück + key : value + """ + print("JSONHANDLER") + if not os.path.exists(file_name): + print("FILE IST OFFEN") + return {} + with open(file_name) as f: + mac_room_mapping = json.load(f) + return mac_room_mapping + +def write_json(mac_room_mapping: dict, file_name: str): + print("ES SCHREIBT IN JASON") + try: + print(f"→ Schreibe Datei: {file_name}") + with open(file_name, "w") as f: + print("FILE IST OPEN") + json.dump(mac_room_mapping, f, indent=4) + print("✅ Datei erfolgreich geschrieben") + except Exception as e: + print("⌠Fehler beim Schreiben:", e) diff --git a/backend/stream_processing/mQTTClientHandler.py b/stream_processing/mQTTClientHandler.py similarity index 93% rename from backend/stream_processing/mQTTClientHandler.py rename to stream_processing/mQTTClientHandler.py index 5d2d022..0ed9e77 100644 --- a/backend/stream_processing/mQTTClientHandler.py +++ b/stream_processing/mQTTClientHandler.py @@ -3,7 +3,7 @@ import json from utils.loggingFactory import LoggerFactory from datetime import datetime import paho.mqtt.client as mqtt -from stream_processing import jsonhandler +import jsonhandler from utils.influx import InfluxDBHelper import os @@ -24,7 +24,9 @@ class MQTTClientHandler: # Konstruktor def __init__( self, broker_url: str, topic: str, influx_writer: InfluxDBHelper + ): + print("DAS IST EIN TEST") self.logger = LoggerFactory.get_logger(__name__) # key: mac : value : room self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME) @@ -38,6 +40,7 @@ class MQTTClientHandler: def on_connect(self, client, userdata, flags, rc): self.logger.info("Connected with result code " + str(rc)) + print("Connected") client.subscribe(self.topic) self.logger.info("Subscribed to " + self.topic) @@ -48,6 +51,9 @@ class MQTTClientHandler: self: ist die MQTTClientHandler instanz, die wird gebraucht um die Einträge in die InfluxDB zu schreiben """ + + print("Message") + msg = json.loads(msg.payload) metadate = msg["metadata"] @@ -60,15 +66,18 @@ class MQTTClientHandler: self.logger.warning( f"Neue MAC-Adresse gefunden: {mac}. Mapping wird ergänzt." ) + print("MAC war nicht in File") self.mac_to_room[mac] = "" # leerer Platzhalter jsonhandler.write_json(self.mac_to_room, self.MAPPING_FILE_NAME) self.mac_to_room = jsonhandler.load_json(self.MAPPING_FILE_NAME) + print("keine Ahnung") return self.write_to_influxDB(msg, metadate) def write_to_influxDB(self, msg: dict, metadate: dict): try: + print(msg) self.influx_writer.write_point( measurement=self.MEASUREMENT_NAME, tags={ diff --git a/backend/stream_processing/mac_to_room.json b/stream_processing/mac_to_room.json similarity index 91% rename from backend/stream_processing/mac_to_room.json rename to stream_processing/mac_to_room.json index c185979..426b33c 100644 --- a/backend/stream_processing/mac_to_room.json +++ b/stream_processing/mac_to_room.json @@ -17,5 +17,7 @@ "a1:b2:c3:d4:e5:f6": "", "77:88:99:aa:bb:cc": "", "test": "", - "aaron": "" + "aaron": "", + "AAFF": "", + "AAFFEE": "" } \ No newline at end of file diff --git a/backend/stream_processing/main.py b/stream_processing/main.py similarity index 62% rename from backend/stream_processing/main.py rename to stream_processing/main.py index 4679c3a..eefb912 100644 --- a/backend/stream_processing/main.py +++ b/stream_processing/main.py @@ -1,19 +1,28 @@ from dotenv import load_dotenv import os -from stream_processing.mQTTClientHandler import MQTTClientHandler +from mQTTClientHandler import MQTTClientHandler from utils.influx import InfluxDBHelper load_dotenv() def main(): + print("🟢 Stream-Processing gestartet", flush=True) influx_writer = InfluxDBHelper( url=os.getenv("INFLUXDB_URL"), token=os.getenv("INFLUXDB_TOKEN"), org=os.getenv("INFLUXDB_ORG"), bucket=os.getenv("INFLUXDB_BUCKET"), + + ) + print("== ENV =="), + print("TOKEN:", os.getenv("INFLUXDB_TOKEN")), + print("URL:", os.getenv("INFLUXDB_URL")), + print("ORG:", os.getenv("INFLUXDB_ORG")), + print("BUCKET:", os.getenv("INFLUXDB_BUCKET")), + mqtt_handler = MQTTClientHandler( broker_url=os.getenv("MQTT_BROKER_URL"), topic=os.getenv("MQTT_TOPIC"), diff --git a/stream_processing/pyproject.toml b/stream_processing/pyproject.toml new file mode 100644 index 0000000..6efd314 --- /dev/null +++ b/stream_processing/pyproject.toml @@ -0,0 +1,46 @@ +[project] +name = "backend" +version = "0.1.0" +description = "backend of co2 web service" +authors = [ + {name = "Patrick Ade", email = "21adpa1bif@hft-stuttgart.de"}, + {name = "Morten Stetter", email = "22stmo1bif@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"} +] +readme = "README.md" +keywords = ["co2", "sensor", "temperature", "humidity", "monitor", "monitoring", "air quality"] + +requires-python = ">=3.12" +dependencies = [ + "influxdb-client>=1.40", + "python-dotenv>=1.1", + "paho-mqtt>=2.1", +] + +[dependency-groups] +dev = [ + "ruff>=0.11.5" +] + +[tool.ruff] +# Set the maximum line length to 80. +line-length = 80 + +[tool.ruff.lint] +# Add the `line-too-long` rule to the enforced rule set. +extend-select = ["E501"] + + +#[build-system] +#requires = ["setuptools" ] #"wheel" +#build-backend = "setuptools.build_meta" + +#[tool.setuptools] +#package-dir = {"" = "."} + +#[tool.setuptools.packages.find] +#where = ["backend"] diff --git a/stream_processing/utils/__init__.py b/stream_processing/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/stream_processing/utils/fluxQueryBuilder.py b/stream_processing/utils/fluxQueryBuilder.py new file mode 100644 index 0000000..16eb1cc --- /dev/null +++ b/stream_processing/utils/fluxQueryBuilder.py @@ -0,0 +1,103 @@ +from typing import List, Optional + + +class FluxQueryBuilder: + """ + A builder class for constructing Flux queries (InfluxDB 2.x). + Supports fluent method chaining for readable query construction. + + Example: + query = ( + FluxQueryBuilder() + .bucket("sensor_data") + .time_range("-1h", "now()") + .filter_measurement("sensor_data") + .filter_fields("co2", "temperature", "humidity") + .filter_field("room", "1/210") + .pivot() + .mean() + .build() + ) + """ + + def __init__(self) -> None: + self._bucket: Optional[str] = None + self._start: Optional[str] = None + self._stop: Optional[str] = None + self._measurement: Optional[str] = None + self._fields: List[str] = [] + self._field_filters: dict = {} # e.g. {"room": "1/210"} + self._use_mean: bool = False + self._use_pivot: bool = False + + def bucket(self, name: str) -> "FluxQueryBuilder": + """Set the InfluxDB bucket name.""" + self._bucket = name + return self + + def time_range(self, start: str, stop: str) -> "FluxQueryBuilder": + """Set time range for the query.""" + self._start = start + self._stop = stop + return self + + def filter_measurement(self, measurement: str) -> "FluxQueryBuilder": + """Filter for a specific _measurement value.""" + self._measurement = measurement + return self + + def filter_field(self, field: str, value: str) -> "FluxQueryBuilder": + """Add a tag filter like r["room"] == "1/210".""" + self._field_filters[field] = value + return self + + def filter_fields(self, *fields: str) -> "FluxQueryBuilder": + """Filter for multiple _field values using OR.""" + self._fields.extend(fields) + return self + + def mean(self) -> "FluxQueryBuilder": + """Apply mean() aggregation.""" + self._use_mean = True + return self + + def pivot(self) -> "FluxQueryBuilder": + """Apply pivot() to restructure results with multiple fields per timestamp.""" + self._use_pivot = True + return self + + def build(self) -> str: + """Construct and return the final Flux query string.""" + if not self._bucket: + raise ValueError("Bucket name is required.") + if not (self._start and self._stop): + raise ValueError("Start and stop times are required.") + if not self._measurement: + raise ValueError("Measurement is required.") + + lines: List[str] = [] + lines.append(f'from(bucket: "{self._bucket}")') + lines.append(f' |> range(start: {self._start}, stop: {self._stop})') + lines.append(f' |> filter(fn: (r) => r["_measurement"] == "{self._measurement}")') + + # Optional tag filters (e.g., room or mac) + for key, value in self._field_filters.items(): + lines.append(f' |> filter(fn: (r) => r["{key}"] == "{value}")') + + # Optional field filters (_field == ...) + if self._fields: + or_expr = " or ".join(f'r["_field"] == "{f}"' for f in self._fields) + lines.append(f' |> filter(fn: (r) => {or_expr})') + + if self._use_mean: + lines.append(' |> mean()') + + if self._use_pivot: + lines.append(' |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")') + + return "\n".join(lines) + + def reset(self) -> "FluxQueryBuilder": + """Reset the builder so a new query can be built from scratch.""" + self.__init__() + return self diff --git a/stream_processing/utils/influx.py b/stream_processing/utils/influx.py new file mode 100644 index 0000000..44fa5c3 --- /dev/null +++ b/stream_processing/utils/influx.py @@ -0,0 +1,52 @@ +import os +from influxdb_client import InfluxDBClient, Point, WritePrecision +from influxdb_client.client.write_api import WriteOptions + + +class InfluxDBHelper: + def __init__(self, url: str, token: str, org: str, bucket: str): + self.client = InfluxDBClient(url=url, token=token, org=org) + self.bucket = bucket + self.org = org + 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=WriteOptions(batch_size=1000, flush_interval=10000) + ) + + def write_point( + self, measurement: str, tags: dict, fields: dict, timestamp=None + ): + """ """ + point = Point(measurement) + for k, v in tags.items(): + point.tag(k, v) + for k, v in fields.items(): + point.field(k, v) + if timestamp: + point.time(timestamp, WritePrecision.NS) + self.write_api.write(bucket=self.bucket, org=self.org, record=point) + + def ping(self) -> bool: + return self.client.ping() + + def get_all_data(self): + """ """ + query = f''' + from(bucket: "{self.bucket}") + |> range(start: -20d) + |> filter(fn: (r) => r["_measurement"] == "sensor_data") + ''' + return self.query_api.query(org=self.org, query=query) + + def get_latest_room_data(self, room_id: str): + """ """ + query = f''' + from(bucket: "{self.bucket}") + |> range(start: -5m) + |> filter(fn: (r) => r["_measurement"] == "co2") + |> filter(fn: (r) => r["room"] == "{room_id}") + |> last() + ''' + return self.query_api.query(org=self.org, query=query) + diff --git a/stream_processing/utils/init.py b/stream_processing/utils/init.py new file mode 100644 index 0000000..e69de29 diff --git a/stream_processing/utils/loggingFactory.py b/stream_processing/utils/loggingFactory.py new file mode 100644 index 0000000..2cc12bf --- /dev/null +++ b/stream_processing/utils/loggingFactory.py @@ -0,0 +1,37 @@ +import logging +import os +from logging.handlers import RotatingFileHandler + +LOG_DIR = "logs" +LOG_FILE = "app.log" +LOG_PATH = os.path.join(LOG_DIR, LOG_FILE) + + +class LoggerFactory: + # logger.info("Connected with result code %s", str(rc)) + # logger.warning("Neue MAC-Adresse gefunden: %s", mac) + # logger.error("Failed writing to InfluxDb: %s", e) + + @staticmethod + def get_logger(name: str, level=logging.DEBUG) -> logging.Logger: + if not os.path.exists(LOG_DIR): + os.makedirs(LOG_DIR) + + logger = logging.getLogger(name) + if logger.hasHandlers(): + return logger # vermeidet doppelte Handler + + logger.setLevel(level) + + formatter = logging.Formatter( + "[%(asctime)s] %(levelname)s in %(name)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + + file_handler = RotatingFileHandler( + LOG_PATH, maxBytes=5_000_000, backupCount=5 + ) + file_handler.setFormatter(formatter) + logger.addHandler(file_handler) + + return logger -- GitLab