I have some code where the arduino Esp8266 is supposed to connect to a flask server hosted on a pi 4 I can get them to connect but I end up getting "192.168.1.20 - - [16/Aug/2023 12:08:59] code 400, message Bad request version ('client!') 192.168.1.20 - - [16/Aug/2023 12:08:59] "This is a webSocket client!" 400 -"
I posted all of the code below exept for the index.html.
any help is greatly appreciated
python
import socket
from flask import Flask, render_template, request
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
# Store a list of discovered Arduino devices
discovered_devices = []
@app.route('/')
def index():
hostname = 'arduino20' # Replace with the actual hostname
return render_template('index.html', discovered_devices=discovered_devices, hostname=hostname)
@app.route('/send_message', methods=['POST'])
def send_message():
message = request.form['message']
# Send the message to all discovered Arduino devices
for device in discovered_devices:
try:
arduino_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
arduino_socket.connect((device['ip'], device['port']))
arduino_socket.sendall((message + '\r').encode()) # Add '\r' to the end of the message
arduino_response = arduino_socket.recv(1024).decode()
arduino_socket.close()
# Emit the Arduino response through WebSocket
socketio.emit('arduino_response', {'response': arduino_response})
except Exception as e:
print(f"Error sending message to {device['ip']}: {str(e)}")
return "Message sent to all discovered Arduino devices"
@socketio.on('connect')
def handle_connect():
print('WebSocket client connected')
# Emit the discovery event to all connected clients
for device in discovered_devices:
socketio.emit('discovery', {'hostname': device['hostname'], 'ip': device['ip'], 'port': device['port']})
@socketio.on('discovery')
def handle_discovery(data):
# Add the discovered device to the list
discovered_devices.append({'hostname': data['hostname'], 'ip': data['ip'], 'port': data['port']})
print(discovered_devices)
if __name__ == '__main__':
socketio.run(app, debug=False, host='0.0.0.0')
arduino ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#include <WebSocketsClient.h>
const char* ssid = "ssid";
const char* password = "password ";
const char* serverAddress = "192.168.1.18"; // Replace with your Flask server IP
const int serverPort = 5000; // Use the appropriate port
WiFiClient wifiClient;
WebSocketsClient webSocket;
WiFiServer server(serverPort);
int LED = 5;
String receivedMessage;
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
webSocket.begin(serverAddress, serverPort);
webSocket.onEvent(webSocketEvent);
// Get the last number of the IP address and use it as the hostname
String ipString = WiFi.localIP().toString();
int lastIndex = ipString.lastIndexOf('.');
String lastNumber = ipString.substring(lastIndex + 1);
String hostname = "arduino" + lastNumber;
// Print out the IP address and port
Serial.println("Arduino IP: " + ipString);
Serial.println("Arduino Port: " + String(serverPort));
// Initialize mDNS
if (!MDNS.begin(hostname.c_str())) {
Serial.println("Error setting up mDNS");
} else {
Serial.println("mDNS responder started with hostname: " + hostname);
}
server.begin();
}
void loop() {
webSocket.loop();
MDNS.update();
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
receivedMessage = client.readStringUntil('\r');
Serial.println("Received message: " + receivedMessage);
// Message processing
commandBreakDown(receivedMessage);
client.println(receivedMessage); // Send the received message back to the client
delay(100);
client.stop();
}
}
}
}
void commandBreakDown(String message) {
int spaceIndex = message.indexOf(' ');
if (spaceIndex != -1) {
String command = message.substring(0, spaceIndex); // Extract the command
// Check if the command is valid
if (command.equals("C1")) {
String valueStr = message.substring(spaceIndex + 1); // Extract the value
int value = valueStr.toInt();
digitalWrite(LED, HIGH); // Turn the LED on
delay(value);
digitalWrite(LED, LOW); // Turn the LED off
}
}
}
//webSocketEvent stuff
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
String discoveryMessage; // Declare the variable here
switch(type) {
case WStype_DISCONNECTED:
Serial.println("WebSocket disconnected");
break;
case WStype_CONNECTED:
Serial.println("WebSocket connected");
// Build the discovery JSON object
discoveryMessage = "{\"hostname\":\"arduino\", \"ip\":\"" + WiFi.localIP().toString() + "\", \"port\":" + String(serverPort) + "}";
webSocket.sendTXT(discoveryMessage.c_str());
break;
case WStype_TEXT:
Serial.printf("Received payload: %s\n", payload);
// Handle text payload, if needed
break;
}
}
Any advice on how to fix it
I think that's an issue with the WebSocket library that you are using. SocketIO and WebSockets are semi-compatible
From SocketIO's docs
Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.
I think that's the message you are getting in Python effectively saying.
"This is a webSocket client!" 400 -" ...not a SocketIo client...go away
I use WebSockets intensively both server/client (Node.js/ESP/Arduino) and it works great (different Arduino library though) but I don't know if that's an option to use native WebSockets or you have to use SocketIO on the server?
There are some Arduino SocketIO libraries Socket.io-Esp-client no idea how good they are but maybe worth having a look.