LovnishVerma's picture
Update app.py
e5d5be1 verified
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
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/status')
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
})
@app.route('/api/reconnect', methods=['POST'])
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)
})
@app.route('/api/toggle', methods=['POST'])
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
@app.route('/api/set_relay', methods=['POST'])
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
@app.route('/api/clear_log', methods=['POST'])
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)