make listener robust to bad data
This commit is contained in:
1546
dashboard/package-lock.json
generated
1546
dashboard/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,13 @@
|
|||||||
"commitId": "a1b2c3d4e5f6"
|
"commitId": "a1b2c3d4e5f6"
|
||||||
},
|
},
|
||||||
"changelog": [
|
"changelog": [
|
||||||
|
{
|
||||||
|
"version": "2025.1.0-alpha.4",
|
||||||
|
"date": "2025-09-01",
|
||||||
|
"changes": [
|
||||||
|
"Grundstruktur für Deployment getestet und optimiert."
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2025.1.0-alpha.3",
|
"version": "2025.1.0-alpha.3",
|
||||||
"date": "2025-08-30",
|
"date": "2025-08-30",
|
||||||
|
|||||||
@@ -123,21 +123,18 @@ services:
|
|||||||
- infoscreen-net
|
- infoscreen-net
|
||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
image: ghcr.io/robbstarkaustria/infoscreen-scheduler:latest # Oder wo auch immer Ihre Images liegen
|
image: ghcr.io/robbstarkaustria/infoscreen-scheduler:latest
|
||||||
container_name: infoscreen-scheduler
|
container_name: infoscreen-scheduler
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
|
# HINZUGEFÜGT: Stellt sicher, dass die DB vor dem Scheduler startet
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
mqtt:
|
mqtt:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
|
# HINZUGEFÜGT: Datenbank-Verbindungsstring
|
||||||
DB_CONN: "mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}"
|
DB_CONN: "mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}"
|
||||||
DB_USER: ${DB_USER}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD}
|
|
||||||
DB_NAME: ${DB_NAME}
|
|
||||||
DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
|
||||||
MQTT_BROKER_URL: mqtt
|
|
||||||
MQTT_PORT: 1883
|
MQTT_PORT: 1883
|
||||||
networks:
|
networks:
|
||||||
- infoscreen-net
|
- infoscreen-net
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ networks:
|
|||||||
services:
|
services:
|
||||||
listener:
|
listener:
|
||||||
build:
|
build:
|
||||||
context: ./listener
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: listener/Dockerfile
|
||||||
image: infoscreen-listener:latest
|
image: infoscreen-listener:latest
|
||||||
container_name: infoscreen-listener
|
container_name: infoscreen-listener
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -16,6 +16,7 @@ services:
|
|||||||
mqtt:
|
mqtt:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
|
- DB_CONN=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}
|
||||||
- DB_URL=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}
|
- DB_URL=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}
|
||||||
# 🔧 ENTFERNT: Volume-Mount ist nur für die Entwicklung
|
# 🔧 ENTFERNT: Volume-Mount ist nur für die Entwicklung
|
||||||
networks:
|
networks:
|
||||||
@@ -80,8 +81,8 @@ services:
|
|||||||
|
|
||||||
server:
|
server:
|
||||||
build:
|
build:
|
||||||
context: ./server
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: server/Dockerfile
|
||||||
image: infoscreen-api:latest
|
image: infoscreen-api:latest
|
||||||
container_name: infoscreen-api
|
container_name: infoscreen-api
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -111,8 +112,8 @@ services:
|
|||||||
# ✅ GEÄNDERT: Dashboard jetzt mit Node.js/React statt Python/Dash
|
# ✅ GEÄNDERT: Dashboard jetzt mit Node.js/React statt Python/Dash
|
||||||
dashboard:
|
dashboard:
|
||||||
build:
|
build:
|
||||||
context: ./dashboard
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: dashboard/Dockerfile
|
||||||
# 🔧 VEREINFACHT: Build-Args werden durch Umgebungsvariablen gesetzt
|
# 🔧 VEREINFACHT: Build-Args werden durch Umgebungsvariablen gesetzt
|
||||||
args:
|
args:
|
||||||
- VITE_API_URL=${API_URL}
|
- VITE_API_URL=${API_URL}
|
||||||
@@ -140,22 +141,23 @@ services:
|
|||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
build:
|
build:
|
||||||
context: ./scheduler
|
dockerfile: scheduler/Dockerfile
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: infoscreen-scheduler:latest
|
image: infoscreen-scheduler:latest
|
||||||
container_name: infoscreen-scheduler
|
container_name: infoscreen-scheduler
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
|
# HINZUGEFÜGT: Stellt sicher, dass die DB vor dem Scheduler startet
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
mqtt:
|
mqtt:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
DB_CONN: "mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}"
|
# HINZUGEFÜGT: Datenbank-Verbindungsstring
|
||||||
MQTT_BROKER_URL: mqtt
|
- DB_CONN=mysql+pymysql://${DB_USER}:${DB_PASSWORD}@db/${DB_NAME}
|
||||||
MQTT_PORT: 1883
|
- MQTT_PORT=1883
|
||||||
networks:
|
networks:
|
||||||
- infoscreen-net
|
- infoscreen-net
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db-data:
|
server-pip-cache:
|
||||||
|
db-data:
|
||||||
|
|||||||
@@ -50,32 +50,35 @@ def on_message(client, userdata, msg):
|
|||||||
# Discovery-Handling
|
# Discovery-Handling
|
||||||
payload = json.loads(msg.payload.decode())
|
payload = json.loads(msg.payload.decode())
|
||||||
logging.info(f"Discovery empfangen: {payload}")
|
logging.info(f"Discovery empfangen: {payload}")
|
||||||
session = Session()
|
if "uuid" in payload:
|
||||||
existing = session.query(Client).filter_by(
|
uuid = payload["uuid"]
|
||||||
uuid=payload["uuid"]).first()
|
session = Session()
|
||||||
if not existing:
|
existing = session.query(Client).filter_by(uuid=uuid).first()
|
||||||
new_client = Client(
|
if not existing:
|
||||||
uuid=payload.get("uuid"),
|
new_client = Client(
|
||||||
hardware_token=payload.get("hardware_token"),
|
uuid=uuid,
|
||||||
ip=payload.get("ip"),
|
hardware_token=payload.get("hardware_token"),
|
||||||
type=payload.get("type"),
|
ip=payload.get("ip"),
|
||||||
hostname=payload.get("hostname"),
|
type=payload.get("type"),
|
||||||
os_version=payload.get("os_version"),
|
hostname=payload.get("hostname"),
|
||||||
software_version=payload.get("software_version"),
|
os_version=payload.get("os_version"),
|
||||||
macs=",".join(payload.get("macs", [])),
|
software_version=payload.get("software_version"),
|
||||||
model=payload.get("model"),
|
macs=",".join(payload.get("macs", [])),
|
||||||
registration_time=datetime.datetime.now(datetime.UTC),
|
model=payload.get("model"),
|
||||||
)
|
registration_time=datetime.datetime.now(datetime.UTC),
|
||||||
session.add(new_client)
|
)
|
||||||
session.commit()
|
session.add(new_client)
|
||||||
logging.info(f"Neuer Client registriert: {payload['uuid']}")
|
session.commit()
|
||||||
|
logging.info(f"Neuer Client registriert: {uuid}")
|
||||||
|
else:
|
||||||
|
logging.info(f"Client bereits bekannt: {uuid}")
|
||||||
|
session.close()
|
||||||
|
# Discovery-ACK senden
|
||||||
|
ack_topic = f"infoscreen/{uuid}/discovery_ack"
|
||||||
|
client.publish(ack_topic, json.dumps({"status": "ok"}))
|
||||||
|
logging.info(f"Discovery-ACK gesendet an {ack_topic}")
|
||||||
else:
|
else:
|
||||||
logging.info(f"Client bereits bekannt: {payload['uuid']}")
|
logging.warning("Discovery ohne UUID empfangen, ignoriert.")
|
||||||
session.close()
|
|
||||||
# Discovery-ACK senden
|
|
||||||
ack_topic = f"infoscreen/{payload['uuid']}/discovery_ack"
|
|
||||||
client.publish(ack_topic, json.dumps({"status": "ok"}))
|
|
||||||
logging.info(f"Discovery-ACK gesendet an {ack_topic}")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Fehler bei Verarbeitung: {e}")
|
logging.error(f"Fehler bei Verarbeitung: {e}")
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||||||
COPY scheduler/ ./scheduler
|
COPY scheduler/ ./scheduler
|
||||||
COPY models/ ./models
|
COPY models/ ./models
|
||||||
ENV PYTHONPATH=/app
|
ENV PYTHONPATH=/app
|
||||||
CMD ["python", "scheduler/scheduler.py"]
|
CMD ["python", "-m", "scheduler.scheduler"]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
from db_utils import get_active_events
|
from .db_utils import get_active_events
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
|||||||
@@ -20,16 +20,16 @@ ENV LANG=de_DE.UTF-8 \
|
|||||||
LC_ALL=de_DE.UTF-8
|
LC_ALL=de_DE.UTF-8
|
||||||
|
|
||||||
# Setze das Arbeitsverzeichnis auf den Workspace-Root, passend zu den Mounts.
|
# Setze das Arbeitsverzeichnis auf den Workspace-Root, passend zu den Mounts.
|
||||||
WORKDIR /workspace
|
WORKDIR /app
|
||||||
|
|
||||||
# Kopiere die Anforderungsdateien in das korrekte Unterverzeichnis.
|
# Kopiere die Anforderungsdateien in das korrekte Unterverzeichnis.
|
||||||
# ✅ KORRIGIERT: Pfade sind jetzt relativ zum Build-Kontext (dem 'server'-Verzeichnis)
|
# ✅ KORRIGIERT: Pfade sind jetzt relativ zum Build-Kontext (dem 'server'-Verzeichnis)
|
||||||
COPY requirements.txt requirements-dev.txt ./
|
COPY server/requirements.txt server/requirements-dev.txt ./server/
|
||||||
|
|
||||||
# Installiere die Python-Abhängigkeiten
|
# Installiere die Python-Abhängigkeiten
|
||||||
RUN pip install --upgrade pip \
|
RUN pip install --upgrade pip \
|
||||||
&& pip install --no-cache-dir -r requirements.txt \
|
&& pip install --no-cache-dir -r server/requirements.txt \
|
||||||
&& pip install --no-cache-dir -r requirements-dev.txt
|
&& pip install --no-cache-dir -r server/requirements-dev.txt
|
||||||
|
|
||||||
# Das Kopieren des Codes ist nicht nötig, da das Verzeichnis gemountet wird.
|
# Das Kopieren des Codes ist nicht nötig, da das Verzeichnis gemountet wird.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user