WebSocket provides real-time, two-way communication between a client (browser) and server.
Traditional HTTP:
WebSocket:
Perfect for: Live dashboards, chat apps, games, sensor monitoring - anything that needs instant updates!
💡 In Your Project: Arduino sensor data flows continuously to your web dashboard without page refreshes!
Install Required Libraries:
pip install flask flask-socketio
Basic Server Structure:
from flask import Flask, render_template
from flask_socketio import SocketIO
# Create Flask app
app = Flask(__name__)
# Initialize SocketIO
socketio = SocketIO(app, cors_allowed_origins="*")
# Route for serving HTML
@app.route('/')
def index():
return render_template('index.html')
# Run server
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0', port=8000)
The @socketio.on() decorator:
Use this to listen for events sent from the browser.
Built-in Events:
'connect' - When a client connects'disconnect' - When a client disconnects💡 Tip: You can create custom event names for different purposes!
from flask_socketio import emit
# Handle new connection
@socketio.on('connect')
def handle_connect():
print('Client connected!')
# Send welcome message to this client
emit('welcome', {'message': 'Hello from server!'})
# Handle disconnection
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
# Handle custom event from client
@socketio.on('my_custom_event')
def handle_custom(data):
print('Received:', data)
emit('response', {'reply': 'Got your message!'})
Two Ways to Send:
1. emit() - Send to current client only
2. socketio.emit() - Send to ALL clients (broadcast)
💡 Your Project: Use broadcast to send sensor data to all connected dashboards!
from flask_socketio import emit
# Send to ONE client (the one who triggered this)
@socketio.on('request_data')
def send_to_one():
emit('data', {'temperature': 25.5})
# Send to ALL clients (broadcast)
def broadcast_sensor_data():
temperature = 25.5 # Read from sensor
socketio.emit('sensor_update', {
'temp': temperature,
'timestamp': time.time()
})
# Example: Broadcast every 2 seconds
def background_task():
while True:
broadcast_sensor_data()
time.sleep(2)
What it does:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
counter = 0
@app.route('/')
def index():
return render_template('index.html')
@socketio.on('connect')
def handle_connect():
# Send current count to new client
emit('counter_update', {'count': counter})
@socketio.on('increment')
def handle_increment():
global counter
counter += 1
# Broadcast to ALL clients
socketio.emit('counter_update', {'count': counter})
if __name__ == '__main__':
socketio.run(app, port=8000)
Include Socket.IO Library:
Add the Socket.IO client library from CDN:
💡 Important: Include this BEFORE your own JavaScript code!
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Example</title>
</head>
<body>
<h1>Real-Time Counter</h1>
<div id="counter">0</div>
<button id="incrementBtn">Increment</button>
<div id="status">Disconnected</div>
<!-- Include Socket.IO library -->
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<!-- Your JavaScript code -->
<script>
// Connect to server
const socket = io();
</script>
</body>
</html>
The io() function:
Creates a connection to your server. By default, it connects to the same server that served the HTML page.
Built-in Events:
'connect' - Connected successfully'disconnect' - Connection lost'error' - Connection error// Initialize connection
const socket = io();
// Listen for successful connection
socket.on('connect', () => {
console.log('Connected to server!');
console.log('My ID:', socket.id);
// Update UI
document.getElementById('status').textContent = 'Connected';
});
// Listen for disconnection
socket.on('disconnect', () => {
console.log('Disconnected from server');
document.getElementById('status').textContent = 'Disconnected';
});
// Listen for errors
socket.on('error', (error) => {
console.error('Error:', error);
});
The socket.on() method:
Listen for events sent from the Python server.
Pattern:
socket.on('event_name', (data) => {
// Handle the data
});
💡 Tip: The event name in JavaScript must match the event name in Python!
// Listen for counter updates from server
socket.on('counter_update', (data) => {
console.log('Received:', data);
// data = { count: 5 }
// Update the display
document.getElementById('counter').textContent = data.count;
});
// Listen for welcome message
socket.on('welcome', (data) => {
console.log('Server says:', data.message);
alert(data.message);
});
// Listen for sensor data (your project)
socket.on('sensor_data', (data) => {
// data = { dht: 25.5, mf52: 25.3 }
document.getElementById('temp').textContent = data.dht + '°C';
});
The socket.emit() method:
Send data from browser to Python server.
Pattern:
socket.emit('event_name', data);
You can send:
// Send simple event (no data)
socket.emit('increment');
// Send with data
socket.emit('set_counter', { value: 10 });
// Example: Button click sends event
document.getElementById('incrementBtn').addEventListener('click', () => {
console.log('Sending increment request');
socket.emit('increment');
});
// Example: Send user input
document.getElementById('sendBtn').addEventListener('click', () => {
const message = document.getElementById('input').value;
socket.emit('chat_message', {
text: message,
timestamp: Date.now()
});
});
Full working example:
This connects to the Python server from Slide 6 and creates a synchronized counter across all clients.
<!DOCTYPE html>
<html>
<head>
<title>Counter Example</title>
</head>
<body>
<h1>Shared Counter</h1>
<div id="counter">0</div>
<button id="incrementBtn">Increment</button>
<div id="status">Disconnected</div>
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
const socket = io();
socket.on('connect', () => {
document.getElementById('status').textContent = 'Connected';
});
socket.on('counter_update', (data) => {
document.getElementById('counter').textContent = data.count;
});
document.getElementById('incrementBtn').addEventListener('click', () => {
socket.emit('increment');
});
</script>
</body>
</html>
What it does:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
@app.route('/')
def index():
return render_template('chat.html')
@socketio.on('connect')
def handle_connect():
print('New user connected')
emit('system_message', {'text': 'Welcome to chat!'})
@socketio.on('send_message')
def handle_message(data):
print(f"Message received: {data['message']}")
# Broadcast to ALL clients
socketio.emit('new_message', {
'username': data['username'],
'message': data['message']
})
if __name__ == '__main__':
socketio.run(app, port=8000)
Complete chat client:
<div id="messages"></div>
<input id="username" placeholder="Your name">
<input id="messageInput" placeholder="Type message">
<button id="sendBtn">Send</button>
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
const socket = io();
socket.on('new_message', (data) => {
const msgDiv = document.createElement('div');
msgDiv.textContent = `${data.username}: ${data.message}`;
document.getElementById('messages').appendChild(msgDiv);
});
document.getElementById('sendBtn').addEventListener('click', () => {
const username = document.getElementById('username').value;
const message = document.getElementById('messageInput').value;
socket.emit('send_message', {
username: username,
message: message
});
document.getElementById('messageInput').value = '';
});
</script>
Continuous sensor broadcasting:
Uses background thread to read sensors and broadcast data every 2 seconds.
from flask import Flask, render_template
from flask_socketio import SocketIO
import threading
import time
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
def read_sensors():
"""Background task: continuously read and broadcast"""
while True:
# Read from Arduino (simplified)
dht_temp = 25.5
mf52_temp = 25.3
# Broadcast to all clients
socketio.emit('sensor_data', {
'dht': dht_temp,
'mf52': mf52_temp,
'timestamp': time.strftime('%H:%M:%S')
})
time.sleep(2)
@socketio.on('connect')
def handle_connect():
print('Dashboard connected')
if __name__ == '__main__':
# Start background thread
thread = threading.Thread(target=read_sensors, daemon=True)
thread.start()
socketio.run(app, port=8000)
Python Server:
@socketio.on('event') - Handle events from clientsemit('event', data) - Send to current clientsocketio.emit('event', data) - Broadcast to all clientsJavaScript Client:
socket.on('event', callback) - Receive from serversocket.emit('event', data) - Send to server✅ Best Practices:
💡 Next Steps: Apply this to your temperature monitoring project!