SwapStation_WebApp/backend/core/mqtt_client.py

76 lines
3.1 KiB
Python

import paho.mqtt.client as mqtt
import uuid
import time
import threading
import socket
class MqttClient:
"""
Handles the connection and message processing for a single MQTT station.
This is a standard Python class, with no GUI dependencies.
"""
def __init__(self, broker, port, user, password, station_id, on_message_callback):
super().__init__()
self.broker = broker
self.port = port
self.user = user
self.password = password
self.station_id = station_id
self.on_message_callback = on_message_callback
# Generate a unique client ID to prevent connection conflicts
unique_id = str(uuid.uuid4())
self.client_id = f"WebApp-Backend-{self.station_id}-{unique_id}"
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, self.client_id)
# Assign callback functions
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.on_disconnect = self.on_disconnect
if self.user and self.password:
self.client.username_pw_set(self.user, self.password)
def on_connect(self, client, userdata, flags, rc, properties):
"""Callback for when the client connects to the broker."""
if rc == 0:
print(f"Successfully connected to MQTT broker for station: {self.station_id}")
# Subscribe to all topics for this station using a wildcard
topic_base = f"VEC/batterySmartStation/v100/{self.station_id}/#"
self.client.subscribe(topic_base)
print(f"Subscribed to: {topic_base}")
else:
print(f"Failed to connect to MQTT for station {self.station_id}, return code {rc}")
def on_disconnect(self, client, userdata, rc, properties):
"""Callback for when the client disconnects."""
print(f"Disconnected from MQTT for station {self.station_id}. Will attempt to reconnect...")
# Paho-MQTT's loop_start() handles automatic reconnection.
def on_message(self, client, userdata, msg):
"""Callback for when a message is received from the broker."""
try:
# Pass the relevant data to the main application's handler
self.on_message_callback(self.station_id, msg.topic, msg.payload)
except Exception as e:
print(f"Error processing message in callback for topic {msg.topic}: {e}")
def connect(self):
"""Connects the client to the MQTT broker."""
print(f"Attempting to connect to {self.broker}:{self.port} with client ID: {self.client_id}")
try:
self.client.connect(self.broker, self.port, 60)
except Exception as e:
print(f"Error connecting to MQTT for station {self.station_id}: {e}")
def start(self):
"""Starts the MQTT client's network loop in a separate thread."""
self.connect()
self.client.loop_start()
def stop(self):
"""Stops the MQTT client's network loop."""
print(f"Stopping MQTT client for station: {self.station_id}")
self.client.loop_stop()