Spaces:
Running
Running
from flask import Flask, render_template, request, jsonify, redirect, url_for | |
import paho.mqtt.client as mqtt | |
import threading | |
import time | |
import json | |
import ssl | |
from datetime import datetime | |
app = Flask(__name__) | |
# MQTT Configuration | |
MQTT_BROKER = "2332bf283a3042789deec54af864c4d4.s1.eu.hivemq.cloud" | |
MQTT_PORT = 8883 | |
MQTT_USER = "nielit212" | |
MQTT_PASSWORD = "iloveMqtt212" | |
MQTT_TOPIC = "212" | |
CLIENT_ID = "Flask_Web_Client" | |
# Global variables | |
relay_state = False | |
connection_status = "Connecting..." | |
last_message_time = None | |
message_log = [] | |
connection_error = None | |
# MQTT Client Setup | |
mqtt_client = mqtt.Client(CLIENT_ID) | |
mqtt_client.username_pw_set(MQTT_USER, MQTT_PASSWORD) | |
# Configure TLS with less strict verification (similar to ESP8266's setInsecure) | |
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) | |
context.check_hostname = False | |
context.verify_mode = ssl.CERT_NONE | |
mqtt_client.tls_set_context(context) | |
def on_connect(client, userdata, flags, rc): | |
global connection_status, connection_error | |
if rc == 0: | |
connection_status = "Connected" | |
connection_error = None | |
print("Connected to MQTT broker") | |
client.subscribe(MQTT_TOPIC) | |
# Subscribe to status topic to get relay state updates | |
client.subscribe(f"{MQTT_TOPIC}/status") | |
# Add connection success to log | |
log_entry = { | |
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
'topic': 'system', | |
'message': 'Connected to MQTT broker' | |
} | |
message_log.append(log_entry) | |
else: | |
error_messages = { | |
1: "Connection refused - incorrect protocol version", | |
2: "Connection refused - invalid client identifier", | |
3: "Connection refused - server unavailable", | |
4: "Connection refused - bad username or password", | |
5: "Connection refused - not authorised" | |
} | |
connection_error = error_messages.get(rc, f"Unknown error code: {rc}") | |
connection_status = f"Failed: {connection_error}" | |
print(f"Failed to connect to MQTT broker: {connection_error}") | |
# Add connection failure to log | |
log_entry = { | |
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
'topic': 'system', | |
'message': f'Connection failed: {connection_error}' | |
} | |
message_log.append(log_entry) | |
def on_message(client, userdata, msg): | |
global relay_state, last_message_time, message_log | |
try: | |
message = msg.payload.decode() | |
last_message_time = datetime.now() | |
# Log the message | |
log_entry = { | |
'timestamp': last_message_time.strftime("%Y-%m-%d %H:%M:%S"), | |
'topic': msg.topic, | |
'message': message | |
} | |
message_log.append(log_entry) | |
# Keep only last 10 messages | |
if len(message_log) > 10: | |
message_log.pop(0) | |
# Update relay state based on message | |
if message == '0': | |
relay_state = True | |
elif message == '1': | |
relay_state = False | |
print(f"Received message: {message} on topic: {msg.topic}") | |
except Exception as e: | |
print(f"Error processing message: {e}") | |
def on_disconnect(client, userdata, rc): | |
global connection_status, connection_error | |
if rc != 0: | |
connection_status = "Disconnected unexpectedly" | |
connection_error = f"Unexpected disconnection (code: {rc})" | |
print(f"Unexpected disconnection from MQTT broker: {rc}") | |
# Add disconnection to log | |
log_entry = { | |
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
'topic': 'system', | |
'message': f'Disconnected unexpectedly (code: {rc})' | |
} | |
message_log.append(log_entry) | |
# Try to reconnect | |
try: | |
time.sleep(5) # Wait 5 seconds before reconnecting | |
client.reconnect() | |
except Exception as e: | |
print(f"Reconnection failed: {e}") | |
else: | |
connection_status = "Disconnected" | |
print("Disconnected from MQTT broker") | |
# Set MQTT callbacks | |
mqtt_client.on_connect = on_connect | |
mqtt_client.on_message = on_message | |
mqtt_client.on_disconnect = on_disconnect | |
def connect_mqtt(): | |
global connection_status, connection_error | |
try: | |
print("Attempting to connect to MQTT broker...") | |
connection_status = "Connecting..." | |
# Set keepalive and connect | |
mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60) | |
mqtt_client.loop_start() | |
# Wait for connection result | |
time.sleep(5) | |
if connection_status == "Connecting...": | |
connection_status = "Connection timeout" | |
connection_error = "Connection attempt timed out" | |
print("Connection attempt timed out") | |
except Exception as e: | |
connection_error = str(e) | |
connection_status = f"Connection error: {str(e)}" | |
print(f"Error connecting to MQTT broker: {e}") | |
# Add connection error to log | |
log_entry = { | |
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
'topic': 'system', | |
'message': f'Connection error: {str(e)}' | |
} | |
message_log.append(log_entry) | |
# Routes | |
def index(): | |
return render_template('index.html') | |
def get_status(): | |
return jsonify({ | |
'relay_state': relay_state, | |
'connection_status': connection_status, | |
'connection_error': connection_error, | |
'last_message_time': last_message_time.strftime("%Y-%m-%d %H:%M:%S") if last_message_time else "Never", | |
'message_log': message_log[-10:] # Only last 10 messages | |
}) | |
def reconnect_mqtt(): | |
global connection_status, connection_error | |
try: | |
if mqtt_client.is_connected(): | |
mqtt_client.disconnect() | |
time.sleep(2) # Wait before reconnecting | |
connection_status = "Reconnecting..." | |
connection_error = None | |
# Reconnect | |
mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60) | |
return jsonify({ | |
'success': True, | |
'message': 'Reconnection initiated' | |
}) | |
except Exception as e: | |
connection_error = str(e) | |
connection_status = f"Reconnection failed: {str(e)}" | |
return jsonify({ | |
'success': False, | |
'error': str(e) | |
}) | |
def toggle_relay(): | |
global relay_state | |
if connection_status != "Connected": | |
return jsonify({'error': 'Not connected to MQTT broker'}), 400 | |
try: | |
# Send command to ESP8266 | |
command = '1' if relay_state else '0' # Opposite of current state | |
mqtt_client.publish(MQTT_TOPIC, command) | |
return jsonify({ | |
'success': True, | |
'message': f'Command sent: {command}', | |
'expected_state': not relay_state | |
}) | |
except Exception as e: | |
return jsonify({'error': str(e)}), 500 | |
def set_relay(): | |
data = request.get_json() | |
if connection_status != "Connected": | |
return jsonify({'error': 'Not connected to MQTT broker'}), 400 | |
try: | |
state = data.get('state', False) | |
command = '0' if state else '1' # ESP8266 expects '0' for ON, '1' for OFF | |
mqtt_client.publish(MQTT_TOPIC, command) | |
return jsonify({ | |
'success': True, | |
'message': f'Command sent: {command}', | |
'expected_state': state | |
}) | |
except Exception as e: | |
return jsonify({'error': str(e)}), 500 | |
def clear_log(): | |
global message_log | |
message_log = [] | |
return jsonify({'success': True, 'message': 'Log cleared'}) | |
if __name__ == '__main__': | |
# Start MQTT connection in a separate thread | |
mqtt_thread = threading.Thread(target=connect_mqtt) | |
mqtt_thread.daemon = True | |
mqtt_thread.start() | |
# Wait a moment for MQTT to connect | |
time.sleep(3) | |
print(f"Starting Flask server...") | |
print(f"MQTT Status: {connection_status}") | |
if connection_error: | |
print(f"MQTT Error: {connection_error}") | |
app.run(debug=True, host='0.0.0.0', port=5000) |