#!/usr/bin/env python3 """ MQTT Publisher Test Script for USDA Vision Camera System This script allows you to manually publish test messages to the MQTT topics to simulate machine state changes for testing purposes. Usage: python mqtt_publisher_test.py The script provides an interactive menu to: 1. Send 'on' state to vibratory conveyor 2. Send 'off' state to vibratory conveyor 3. Send 'on' state to blower separator 4. Send 'off' state to blower separator 5. Send custom message """ import paho.mqtt.client as mqtt import time import sys from datetime import datetime # MQTT Configuration (matching your system config) MQTT_BROKER_HOST = "192.168.1.110" MQTT_BROKER_PORT = 1883 MQTT_USERNAME = None # Set if your broker requires authentication MQTT_PASSWORD = None # Set if your broker requires authentication # Topics (from your config.json) MQTT_TOPICS = { "vibratory_conveyor": "vision/vibratory_conveyor/state", "blower_separator": "vision/blower_separator/state" } class MQTTPublisher: def __init__(self): self.client = None self.connected = False def setup_client(self): """Setup MQTT client""" try: self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1) self.client.on_connect = self.on_connect self.client.on_disconnect = self.on_disconnect self.client.on_publish = self.on_publish if MQTT_USERNAME and MQTT_PASSWORD: self.client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD) return True except Exception as e: print(f"āŒ Error setting up MQTT client: {e}") return False def connect(self): """Connect to MQTT broker""" try: print(f"šŸ”— Connecting to MQTT broker at {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}...") self.client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT, 60) self.client.loop_start() # Start background loop # Wait for connection timeout = 10 start_time = time.time() while not self.connected and (time.time() - start_time) < timeout: time.sleep(0.1) return self.connected except Exception as e: print(f"āŒ Failed to connect to MQTT broker: {e}") return False def disconnect(self): """Disconnect from MQTT broker""" if self.client: self.client.loop_stop() self.client.disconnect() def on_connect(self, client, userdata, flags, rc): """Callback when client connects""" if rc == 0: self.connected = True print(f"āœ… Connected to MQTT broker successfully!") else: self.connected = False print(f"āŒ Connection failed with return code {rc}") def on_disconnect(self, client, userdata, rc): """Callback when client disconnects""" self.connected = False print(f"šŸ”Œ Disconnected from MQTT broker") def on_publish(self, client, userdata, mid): """Callback when message is published""" print(f"šŸ“¤ Message published successfully (mid: {mid})") def publish_message(self, topic, payload): """Publish a message to a topic""" if not self.connected: print("āŒ Not connected to MQTT broker") return False try: timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3] print(f"šŸ“” [{timestamp}] Publishing message:") print(f" šŸ“ Topic: {topic}") print(f" šŸ“„ Payload: '{payload}'") result = self.client.publish(topic, payload) if result.rc == mqtt.MQTT_ERR_SUCCESS: print(f"āœ… Message queued for publishing") return True else: print(f"āŒ Failed to publish message (error: {result.rc})") return False except Exception as e: print(f"āŒ Error publishing message: {e}") return False def show_menu(self): """Show interactive menu""" print("\n" + "=" * 50) print("šŸŽ›ļø MQTT PUBLISHER TEST MENU") print("=" * 50) print("1. Send 'on' to vibratory conveyor") print("2. Send 'off' to vibratory conveyor") print("3. Send 'on' to blower separator") print("4. Send 'off' to blower separator") print("5. Send custom message") print("6. Show current topics") print("0. Exit") print("-" * 50) def handle_menu_choice(self, choice): """Handle menu selection""" if choice == "1": self.publish_message(MQTT_TOPICS["vibratory_conveyor"], "on") elif choice == "2": self.publish_message(MQTT_TOPICS["vibratory_conveyor"], "off") elif choice == "3": self.publish_message(MQTT_TOPICS["blower_separator"], "on") elif choice == "4": self.publish_message(MQTT_TOPICS["blower_separator"], "off") elif choice == "5": self.custom_message() elif choice == "6": self.show_topics() elif choice == "0": return False else: print("āŒ Invalid choice. Please try again.") return True def custom_message(self): """Send custom message""" print("\nšŸ“ Custom Message") print("Available topics:") for i, (name, topic) in enumerate(MQTT_TOPICS.items(), 1): print(f" {i}. {name}: {topic}") try: topic_choice = input("Select topic (1-2): ").strip() if topic_choice == "1": topic = MQTT_TOPICS["vibratory_conveyor"] elif topic_choice == "2": topic = MQTT_TOPICS["blower_separator"] else: print("āŒ Invalid topic choice") return payload = input("Enter message payload: ").strip() if payload: self.publish_message(topic, payload) else: print("āŒ Empty payload, message not sent") except KeyboardInterrupt: print("\nāŒ Cancelled") def show_topics(self): """Show configured topics""" print("\nšŸ“‹ Configured Topics:") for name, topic in MQTT_TOPICS.items(): print(f" šŸ­ {name}: {topic}") def run(self): """Main interactive loop""" print("šŸ“¤ MQTT Publisher Test") print("=" * 50) print(f"šŸŽÆ Broker: {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}") if not self.setup_client(): return False if not self.connect(): print("āŒ Failed to connect to MQTT broker") return False try: while True: self.show_menu() choice = input("Enter your choice: ").strip() if not self.handle_menu_choice(choice): break except KeyboardInterrupt: print("\n\nšŸ›‘ Interrupted by user") except Exception as e: print(f"\nāŒ Error: {e}") finally: self.disconnect() print("šŸ‘‹ Goodbye!") return True def main(): """Main function""" publisher = MQTTPublisher() try: publisher.run() except Exception as e: print(f"āŒ Unexpected error: {e}") sys.exit(1) if __name__ == "__main__": main()