diff --git a/tools/selector-webapp/app.py b/tools/selector-webapp/app.py index 07f57f57ed6d1fd5330a16d3cff3be3aa93f60c8..a5782758a4e1cf5978a771d89b061b0d94f20d3d 100644 --- a/tools/selector-webapp/app.py +++ b/tools/selector-webapp/app.py @@ -1,59 +1,32 @@ from flask import Flask, render_template, request, jsonify import paho.mqtt.client as mqtt -# Flask app initialization app = Flask(__name__) # MQTT Configuration -BROKER = "localhost" # Replace with your broker -PUBLISH_TOPIC = "colors/publish" -LOG_TOPIC = "colors/log" - +BROKER = "localhost" # Change if using a remote broker +PORT = 1883 mqtt_client = mqtt.Client() -# On connect, subscribe to the log topic -def on_connect(client, userdata, flags, rc): - print(f"Connected to MQTT Broker with result code {rc}") - mqtt_client.subscribe(LOG_TOPIC) - -# On receiving a message, print it -log_messages = [] - -def on_message(client, userdata, msg): - global log_messages - message = msg.payload.decode() - log_messages.append(message) - -# Assign MQTT event handlers -mqtt_client.on_connect = on_connect -mqtt_client.on_message = on_message - -# Connect to the broker -mqtt_client.connect(BROKER, 1884, 60) +# Connect to MQTT broker +mqtt_client.connect(BROKER, PORT, 60) mqtt_client.loop_start() -# Route for the main page @app.route('/') def index(): - # List of colors to display as buttons - colors = ["red", "blue", "green"] - return render_template('index.html', colors=colors) + return render_template('index.html') -# Route to handle button press @app.route('/publish', methods=['POST']) def publish(): - color = request.json.get("color") - if color: - topic = f"/{color}" # Each color gets its own topic - mqtt_client.publish(topic, color) - return jsonify({"status": "success", "topic": topic, "color": color}) - return jsonify({"status": "error"}), 400 - - -# Route to fetch log messages -@app.route('/logs', methods=['GET']) -def get_logs(): - return jsonify(log_messages) + data = request.json + topic = data.get("topic") + message = data.get("message") + + if topic and message in ["true", "false"]: + mqtt_client.publish(topic, message) + return jsonify({"status": "success", "topic": topic, "message": message}) + + return jsonify({"status": "error", "message": "Invalid input"}), 400 if __name__ == '__main__': app.run(debug=True) diff --git a/tools/selector-webapp/templates/index.html b/tools/selector-webapp/templates/index.html index 758137128e02b81faefdbd27654a9e9d37febefb..6a95285e230ad69a11cbb4b753dfd56d58598534 100644 --- a/tools/selector-webapp/templates/index.html +++ b/tools/selector-webapp/templates/index.html @@ -3,137 +3,122 @@ <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <title>Selector</title> - <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet"> + <title>MQTT Publisher</title> <style> body { - font-family: 'Inter', sans-serif; + font-family: Arial, sans-serif; + background-color: #f4f7fc; margin: 0; - padding: 0; - background-color: #f4f4f9; - color: #333; + padding: 20px; } - header { - background-color: #4a90e2; - color: white; - padding: 15px 20px; + + h1 { text-align: center; - font-size: 24px; - font-weight: 600; + color: #333; } - main { - max-width: 800px; - margin: 20px auto; + + .container { + max-width: 500px; + margin: 0 auto; + background-color: white; padding: 20px; - background: white; - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); - border-radius: 10px; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } - h1 { - font-size: 28px; - margin-bottom: 20px; - color: #4a90e2; + + label { + font-size: 16px; + margin-bottom: 8px; + display: block; + color: #555; } - .buttons-container { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 15px; + + select { + width: 100%; + padding: 10px; + margin-bottom: 20px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #fafafa; } - .color-button { - display: inline-block; - width: 120px; - height: 120px; + + button { + width: 100%; + padding: 12px; + background-color: #4CAF50; + color: white; + font-size: 16px; border: none; - border-radius: 10px; + border-radius: 5px; cursor: pointer; - font-size: 18px; - font-weight: 600; - color: white; - text-transform: capitalize; - transition: transform 0.2s, box-shadow 0.2s; + transition: background-color 0.3s; } - .color-button:hover { - transform: translateY(-3px); - box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); + + button:hover { + background-color: #45a049; } - #log-container { - margin-top: 30px; + + .form-group { + margin-bottom: 20px; } - #log-container h2 { - font-size: 22px; - margin-bottom: 15px; + + .form-group:last-child { + margin-bottom: 0; } - .log-item { - padding: 10px 15px; - margin-bottom: 10px; - background-color: #f9f9f9; - border-left: 4px solid #4a90e2; - border-radius: 5px; - font-size: 14px; - color: #555; + + .message { + font-size: 18px; + text-align: center; + margin-top: 20px; } </style> + <script> + async function sendMessage() { + const topic = document.getElementById("topic").value; + const message = document.getElementById("message").value; + + const response = await fetch('/publish', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ topic, message }) + }); + + const result = await response.json(); + alert(result.status === "success" ? "Message Sent!" : "Error Sending Message"); + } + </script> </head> <body> - <header>Selector</header> - <main> - <h1>Select a Color</h1> - <div class="buttons-container"> - {% for color in colors %} - <button - class="color-button" - style="background-color: {{ color }};" - onclick="sendColor('{{ color }}')"> - {{ color }} - </button> - {% endfor %} - </div> - <div id="log-container"> - <h2>Logs</h2> - <div id="logs"> - <!-- Logs will be dynamically updated --> - </div> + <h1>MQTT Publisher</h1> + + <div class="container"> + <div class="form-group"> + <label for="topic">Topic:</label> + <select id="topic"> + <option value="Red">Red</option> + <option value="Green">Green</option> + <option value="Blue">Blue</option> + <option value="PickSuccess">PickSuccess</option> + <option value="PlaceSuccess">PlaceSuccess</option> + <option value="PickFail">PickFail</option> + <option value="PlaceFail">PlaceFail</option> + <option value="Stop">Stop</option> + <option value="Sensor">Sensor</option> + </select> </div> - </main> - <script> - // Function to send color to the server - async function sendColor(color) { - try { - const response = await fetch('/publish', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ color: color }), - }); - const result = await response.json(); - if (result.status === "success") { - alert(`Color "${result.color}" sent successfully!`); - } else { - alert("Error sending color."); - } - } catch (error) { - console.error("Error:", error); - } - } + <div class="form-group"> + <label for="message">Message:</label> + <select id="message"> + <option value="true">true</option> + <option value="false">false</option> + </select> + </div> - // Function to fetch logs - async function fetchLogs() { - try { - const response = await fetch('/logs'); - const logs = await response.json(); - const logsContainer = document.getElementById("logs"); - logsContainer.innerHTML = logs.map(log => `<div class="log-item">${log}</div>`).join(""); - } catch (error) { - console.error("Error fetching logs:", error); - } - } + <button onclick="sendMessage()">Publish</button> + </div> - // Fetch logs every 2 seconds - setInterval(fetchLogs, 2000); - </script> </body> </html>