217 lines
9.0 KiB
Python
217 lines
9.0 KiB
Python
# # In core/mqtt_client.py
|
|
# import socket
|
|
# from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
|
|
# import paho.mqtt.client as mqtt
|
|
# import uuid
|
|
|
|
# class MqttClient(QObject):
|
|
# # --- MODIFIED SIGNAL: Now sends a bool and a string ---
|
|
# connection_status_changed = pyqtSignal(bool, str)
|
|
# message_received = pyqtSignal(str, bytes)
|
|
# connection_error = pyqtSignal(str)
|
|
# stop_logging_signal = pyqtSignal()
|
|
# connected = pyqtSignal()
|
|
# disconnected = pyqtSignal()
|
|
|
|
# def __init__(self, broker, port, user, password, client_id):
|
|
# super().__init__()
|
|
# self.broker = broker
|
|
# self.port = port
|
|
|
|
# self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id)
|
|
# if user and password:
|
|
# self.client.username_pw_set(user, password)
|
|
|
|
# self.client.on_connect = self.on_connect
|
|
# self.client.on_disconnect = self.on_disconnect
|
|
# self.client.on_message = self.on_message
|
|
# # self.client.on_subscribe = self.on_subscribe
|
|
|
|
# def on_connect(self, client, userdata, flags, rc, properties):
|
|
# if rc == 0:
|
|
# print("Connection to MQTT Broker successful!")
|
|
# self.connection_status_changed.emit(True, "✅ Connected")
|
|
# self.connected.emit()
|
|
# # The app is connected, so we should NOT emit disconnected signals here.
|
|
# else:
|
|
# print(f"Failed to connect, return code {rc}\n")
|
|
# self.connection_status_changed.emit(False, f"❌ Connection failed (Code: {rc})")
|
|
# self.disconnected.emit() # Connection failed, so we are disconnected
|
|
|
|
# def on_disconnect(self, client, userdata, flags, rc, properties):
|
|
# print("Disconnected from MQTT Broker.")
|
|
# # Correctly emit signals for a disconnection
|
|
# # Change the icon in the line below from 🔌 to 🔴 ❌ 🚫 💔
|
|
# self.connection_status_changed.emit(False, "💔 Disconnected")
|
|
# self.disconnected.emit()
|
|
# self.stop_logging_signal.emit() # It's appropriate to stop logging here
|
|
|
|
# def on_message(self, client, userdata, msg):
|
|
# # print(f"Received {len(msg.payload)} bytes of binary data from topic `{msg.topic}`")
|
|
# self.message_received.emit(msg.topic, msg.payload)
|
|
|
|
# # --- MODIFIED connect_to_broker METHOD ---
|
|
# def connect_to_broker(self):
|
|
# print(f"Attempting to connect to {self.broker}:{self.port}...")
|
|
# try:
|
|
# self.client.connect(self.broker, self.port, 120)
|
|
# print(f"Attempting to connect to {self.broker}:{self.port}...")
|
|
# self.client.loop_start()
|
|
# except socket.gaierror:
|
|
# msg = "Host not found. Check internet."
|
|
# print(f"❌ Connection Error: {msg}")
|
|
# self.connection_status_changed.emit(False, f"❌ {msg}")
|
|
# except (socket.error, TimeoutError):
|
|
# msg = "Connection failed. Server offline?"
|
|
# print(f"❌ Connection Error: {msg}")
|
|
# self.connection_status_changed.emit(False, f"❌ {msg}")
|
|
# except Exception as e:
|
|
# msg = f"An unexpected error occurred: {e}"
|
|
# print(f"❌ {msg}")
|
|
# self.connection_status_changed.emit(False, f"❌ Error")
|
|
|
|
|
|
# def run(self):
|
|
# """
|
|
# Connects to the broker and starts the network loop.
|
|
# Handles all common connection errors gracefully.
|
|
# """
|
|
# print(f"Attempting to connect to {self.broker}:{self.port}...")
|
|
# try:
|
|
# # 1. Attempt to connect
|
|
# # print(f"Attempting to connect to {self.broker}:{self.port}...")
|
|
# self.client.connect(self.broker, self.port, 120)
|
|
|
|
# # 2. Run the blocking network loop
|
|
# # This will run until self.client.disconnect() is called
|
|
# self.client.loop_forever()
|
|
|
|
# except socket.gaierror:
|
|
# msg = "Host not found. Check the broker address or your internet connection."
|
|
# print(f"❌ {msg}")
|
|
# self.connection_error.emit(msg) # Report error to the main window
|
|
|
|
# except (socket.error, ConnectionRefusedError):
|
|
# msg = "Connection refused. Is the server offline or the port incorrect?"
|
|
# print(f"❌ {msg}")
|
|
# self.connection_error.emit(msg)
|
|
|
|
# except TimeoutError:
|
|
# msg = "Connection timed out. The server is not responding."
|
|
# print(f"❌ {msg}")
|
|
# self.connection_error.emit(msg)
|
|
|
|
# except Exception as e:
|
|
# # Catch any other unexpected errors during connection or loop
|
|
# msg = f"An unexpected error occurred: {e}"
|
|
# print(f"❌ {msg}")
|
|
# self.connection_error.emit(msg)
|
|
|
|
# # def on_subscribe(self, client, userdata, mid, reason_code_list, properties):
|
|
# # """Callback function for when the broker responds to a subscription request."""
|
|
# # if reason_code_list[0].is_failure:
|
|
# # print(f"❌ Broker rejected subscription: {reason_code_list[0]}")
|
|
# # else:
|
|
# # print(f"✅ Broker accepted subscription with QoS: {reason_code_list[0].value}")
|
|
|
|
# # --- (The rest of the file remains the same) ---
|
|
# @pyqtSlot()
|
|
# def disconnect_from_broker(self):
|
|
# """Stops the MQTT client's network loop."""
|
|
# if self.client:
|
|
# self.client.loop_stop()
|
|
# self.client.disconnect()
|
|
# print("Stopping MQTT network loop.")
|
|
|
|
# def subscribe_to_topic(self, topic): # Add qos parameter
|
|
# print(f"Subscribing to topic: {topic}")
|
|
# self.client.subscribe(topic)
|
|
|
|
# def publish_message(self, topic, payload):
|
|
# self.client.publish(topic, payload)
|
|
|
|
# def cleanup(self):
|
|
# print("Stopping MQTT network loop.")
|
|
# self.client.loop_stop()
|
|
|
|
|
|
# In core/mqtt_client.py
|
|
import socket
|
|
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
|
|
import paho.mqtt.client as mqtt
|
|
|
|
class MqttClient(QObject):
|
|
# Sends connection state (bool) and a message (str)
|
|
connection_status_changed = pyqtSignal(bool, str)
|
|
# Generic signals for success or failure/disconnection
|
|
connected = pyqtSignal()
|
|
disconnected = pyqtSignal()
|
|
stop_logging_signal = pyqtSignal()
|
|
# Sends topic (str) and payload (bytes) when a message is received
|
|
message_received = pyqtSignal(str, bytes)
|
|
|
|
def __init__(self, broker, port, user, password, client_id):
|
|
super().__init__()
|
|
self.broker = broker
|
|
self.port = port
|
|
|
|
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id)
|
|
if user and password:
|
|
self.client.username_pw_set(user, password)
|
|
|
|
self.client.on_connect = self.on_connect
|
|
self.client.on_disconnect = self.on_disconnect
|
|
self.client.on_message = self.on_message
|
|
|
|
def on_connect(self, client, userdata, flags, rc, properties):
|
|
if rc == 0:
|
|
print("Connection to MQTT Broker successful!")
|
|
self.connection_status_changed.emit(True, "✅ Connected")
|
|
self.connected.emit()
|
|
else:
|
|
print(f"Failed to connect, return code {rc}\n")
|
|
self.connection_status_changed.emit(False, f"❌ Connection failed (Code: {rc})")
|
|
self.disconnected.emit()
|
|
|
|
def on_disconnect(self, client, userdata, flags, rc, properties):
|
|
print("Disconnected from MQTT Broker.")
|
|
self.connection_status_changed.emit(False, "💔 Disconnected")
|
|
self.disconnected.emit()
|
|
self.stop_logging_signal.emit()
|
|
|
|
def on_message(self, client, userdata, msg):
|
|
self.message_received.emit(msg.topic, msg.payload)
|
|
|
|
@pyqtSlot()
|
|
def connect_to_broker(self):
|
|
print(f"Attempting to connect to {self.broker}:{self.port}...")
|
|
try:
|
|
self.client.connect(self.broker, self.port, 60)
|
|
self.client.loop_start()
|
|
except socket.gaierror:
|
|
msg = "Host not found. Check broker address or your internet connection."
|
|
print(f"❌ Connection Error: {msg}")
|
|
self.connection_status_changed.emit(False, msg)
|
|
except (socket.error, ConnectionRefusedError, TimeoutError):
|
|
msg = "Connection failed. Is the server offline or the port incorrect?"
|
|
print(f"❌ Connection Error: {msg}")
|
|
self.connection_status_changed.emit(False, msg)
|
|
except Exception as e:
|
|
msg = f"An unexpected error occurred: {e}"
|
|
print(f"❌ {msg}")
|
|
self.connection_status_changed.emit(False, f"Error: {e}")
|
|
|
|
@pyqtSlot()
|
|
def disconnect_from_broker(self):
|
|
if self.client:
|
|
self.client.loop_stop()
|
|
self.client.disconnect()
|
|
print("Stopping MQTT network loop.")
|
|
|
|
def subscribe_to_topic(self, topic):
|
|
print(f"Subscribing to topic: {topic}")
|
|
self.client.subscribe(topic)
|
|
|
|
def publish_message(self, topic, payload):
|
|
self.client.publish(topic, payload)
|