Flask 和 ESP8266 通过 SocketIO 通信(更新 2x)
Communication between Flask and ESP8266 via SocketIO (Updated 2x)
我有一个小型网络应用程序,其后端是 Flask+SocketIO 服务器。我想从 ESP8266 获取一些数据到我的应用程序中。我能想到的最简单的实现方式是将微控制器直接连接到后端。
我正在使用timum-viw library with this example code在微控制器上实现客户端。
问题是在尝试 运行 我得到的例子时
(12765) accepted ('192.168.0.11', 59848)
192.168.0.11 - - [06/Jul/2020 18:15:25] "GET /socket.io/?transport=websocket HTTP/1.1" 400 122 0.000265
192.168.0.11 - - [06/Jul/2020 18:15:31] code 400, message Bad request syntax ('This is a webSocket client!')
192.168.0.11 - - [06/Jul/2020 18:15:31] "This is a webSocket client!" 400 -
在开发服务器的终端window中。 (IP属于ESP8266。)
我对 arduinoWebSockets library and the WebSocketClientSocketIO 示例有相同的体验。
你能帮我找出问题所在吗?
更新
此时一切都在本地托管。我正在 运行 使用 python3 flask_main.py
安装 flask 开发服务器,安装了 eventlet。
显示问题的最少代码:
Arduino:
#include <SocketIoClient.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <Hash.h>
#define USE_SERIAL Serial
#define SSID_primary "**********"
#define WIFI_PWD_primary "**********"
#define SERVER_IP "192.168.0.7"
#define SERVER_PORT 5005
ESP8266WiFiMulti wifiMulti;
SocketIoClient socketIOClient;
void setup() {
//// set up serial communication
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
//// connect to some access point
wifiMulti.addAP(SSID_primary, WIFI_PWD_primary);
while(wifiMulti.run() != WL_CONNECTED) {
delay(500);
USE_SERIAL.print("Looking for WiFi ");
}
USE_SERIAL.printf("Connected to %s\n", WiFi.SSID().c_str());
USE_SERIAL.printf("My local IP address is %s\n", WiFi.localIP().toString().c_str());
//// set up socket communication
socketIOClient.begin(SERVER_IP, SERVER_PORT);
}
void loop() {
socketIOClient.emit("message", "\"hi there :)\"");
socketIOClient.loop();
delay(1000);
}
Flask 最小代码:
from flask import Flask, render_template, request
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
@socketio.on('message')
def handle_message_event(msg):
print('received msg from {} : {}'.format(request.remote_addr, str(msg)))
if __name__ == '__main__':
socketio.run(app, host="0.0.0.0", port=5005, debug=True)
以下代码仅供调试使用。我不希望以后以任何形式使用它们。
奇怪的是,Arduino 代码在 node.js 服务器上运行良好:
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(5005);
io.attach(http, {
pingInterval: 10000,
pingTimeout: 5000,
cookie: false
});
io.on('connection', function (socket) {
console.log('user connected');
socket.on('disconnect', function () {
console.log('user disconnected');
});
socket.on('message', function (msg) {
console.log("message: "+msg);
});
timeout();
});
http.listen();
我的 Flask 会不会有什么问题?它响应来自以下的连接:
from socketIO_client import SocketIO, LoggingNamespace
socketIO = SocketIO('localhost', 5005, LoggingNamespace)
while True:
_ = raw_input("> ")
socketIO.emit('message', "hello 2")
但是节点服务器没有!
更新 2
所以我继续查看与 wire shark 的通信:
Python 客户端和 Flask 服务器(有效)
第27帧的有效载荷:
Hypertext Transfer Protocol
GET /socket.io/?EIO=3&transport=websocket&sid=8f47e9a521404b66b23cd985cdee049d HTTP/1.1\r\n
Upgrade: websocket\r\n
Host: localhost:5005\r\n
Origin: http://localhost:5005\r\n
Sec-WebSocket-Key: TQ589ew7EgwDILWb50Eu9Q==\r\n
Sec-WebSocket-Version: 13\r\n
Connection: upgrade\r\n
Connection: keep-alive\r\n
Accept-Encoding: gzip, deflate\r\n
Accept: */*\r\n
User-Agent: python-requests/2.18.4\r\n
\r\n
[Full request URI: http://localhost:5005/socket.io/?EIO=3&transport=websocket&sid=8f47e9a521404b66b23cd985cdee049d]
[HTTP request 1/1]
[Response in frame: 29]
对 arduino 和 flask 做同样的事情(不起作用)
第34帧的有效载荷:
Hypertext Transfer Protocol
GET /socket.io/?transport=websocket HTTP/1.1\r\n
Host: 192.168.0.7:5005\r\n
Connection: Upgrade\r\n
Upgrade: websocket\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: D9+/7YOHoA8lW7a/0V8vsA==\r\n
Sec-WebSocket-Protocol: arduino\r\n
Origin: file://\r\n
User-Agent: arduino-WebSocket-Client\r\n
\r\n
[Full request URI: http://192.168.0.7:5005/socket.io/?transport=websocket]
[HTTP request 1/1]
[Response in frame: 36]
事实证明,Flask 对
Origin: file://\r\n
部分是因为它认为它是 CORS。这就是为什么 actually works, however I think it is the wrong fix. Removing this extra header entry is the right way to go about this. This is most simply done by editing this line 匹配这个:
_client.extraHeaders = WEBSOCKETS_STRING("");
在您当地的图书馆。
研究了好几个小时 :D
我有一个小型网络应用程序,其后端是 Flask+SocketIO 服务器。我想从 ESP8266 获取一些数据到我的应用程序中。我能想到的最简单的实现方式是将微控制器直接连接到后端。
我正在使用timum-viw library with this example code在微控制器上实现客户端。
问题是在尝试 运行 我得到的例子时
(12765) accepted ('192.168.0.11', 59848)
192.168.0.11 - - [06/Jul/2020 18:15:25] "GET /socket.io/?transport=websocket HTTP/1.1" 400 122 0.000265
192.168.0.11 - - [06/Jul/2020 18:15:31] code 400, message Bad request syntax ('This is a webSocket client!')
192.168.0.11 - - [06/Jul/2020 18:15:31] "This is a webSocket client!" 400 -
在开发服务器的终端window中。 (IP属于ESP8266。)
我对 arduinoWebSockets library and the WebSocketClientSocketIO 示例有相同的体验。
你能帮我找出问题所在吗?
更新
此时一切都在本地托管。我正在 运行 使用 python3 flask_main.py
安装 flask 开发服务器,安装了 eventlet。
显示问题的最少代码:
Arduino:
#include <SocketIoClient.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <Hash.h>
#define USE_SERIAL Serial
#define SSID_primary "**********"
#define WIFI_PWD_primary "**********"
#define SERVER_IP "192.168.0.7"
#define SERVER_PORT 5005
ESP8266WiFiMulti wifiMulti;
SocketIoClient socketIOClient;
void setup() {
//// set up serial communication
USE_SERIAL.begin(115200);
USE_SERIAL.setDebugOutput(true);
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
//// connect to some access point
wifiMulti.addAP(SSID_primary, WIFI_PWD_primary);
while(wifiMulti.run() != WL_CONNECTED) {
delay(500);
USE_SERIAL.print("Looking for WiFi ");
}
USE_SERIAL.printf("Connected to %s\n", WiFi.SSID().c_str());
USE_SERIAL.printf("My local IP address is %s\n", WiFi.localIP().toString().c_str());
//// set up socket communication
socketIOClient.begin(SERVER_IP, SERVER_PORT);
}
void loop() {
socketIOClient.emit("message", "\"hi there :)\"");
socketIOClient.loop();
delay(1000);
}
Flask 最小代码:
from flask import Flask, render_template, request
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
@socketio.on('message')
def handle_message_event(msg):
print('received msg from {} : {}'.format(request.remote_addr, str(msg)))
if __name__ == '__main__':
socketio.run(app, host="0.0.0.0", port=5005, debug=True)
以下代码仅供调试使用。我不希望以后以任何形式使用它们。
奇怪的是,Arduino 代码在 node.js 服务器上运行良好:
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(5005);
io.attach(http, {
pingInterval: 10000,
pingTimeout: 5000,
cookie: false
});
io.on('connection', function (socket) {
console.log('user connected');
socket.on('disconnect', function () {
console.log('user disconnected');
});
socket.on('message', function (msg) {
console.log("message: "+msg);
});
timeout();
});
http.listen();
我的 Flask 会不会有什么问题?它响应来自以下的连接:
from socketIO_client import SocketIO, LoggingNamespace
socketIO = SocketIO('localhost', 5005, LoggingNamespace)
while True:
_ = raw_input("> ")
socketIO.emit('message', "hello 2")
但是节点服务器没有!
更新 2
所以我继续查看与 wire shark 的通信:
Python 客户端和 Flask 服务器(有效)
第27帧的有效载荷:
Hypertext Transfer Protocol
GET /socket.io/?EIO=3&transport=websocket&sid=8f47e9a521404b66b23cd985cdee049d HTTP/1.1\r\n
Upgrade: websocket\r\n
Host: localhost:5005\r\n
Origin: http://localhost:5005\r\n
Sec-WebSocket-Key: TQ589ew7EgwDILWb50Eu9Q==\r\n
Sec-WebSocket-Version: 13\r\n
Connection: upgrade\r\n
Connection: keep-alive\r\n
Accept-Encoding: gzip, deflate\r\n
Accept: */*\r\n
User-Agent: python-requests/2.18.4\r\n
\r\n
[Full request URI: http://localhost:5005/socket.io/?EIO=3&transport=websocket&sid=8f47e9a521404b66b23cd985cdee049d]
[HTTP request 1/1]
[Response in frame: 29]
对 arduino 和 flask 做同样的事情(不起作用)
第34帧的有效载荷:
Hypertext Transfer Protocol
GET /socket.io/?transport=websocket HTTP/1.1\r\n
Host: 192.168.0.7:5005\r\n
Connection: Upgrade\r\n
Upgrade: websocket\r\n
Sec-WebSocket-Version: 13\r\n
Sec-WebSocket-Key: D9+/7YOHoA8lW7a/0V8vsA==\r\n
Sec-WebSocket-Protocol: arduino\r\n
Origin: file://\r\n
User-Agent: arduino-WebSocket-Client\r\n
\r\n
[Full request URI: http://192.168.0.7:5005/socket.io/?transport=websocket]
[HTTP request 1/1]
[Response in frame: 36]
事实证明,Flask 对
Origin: file://\r\n
部分是因为它认为它是 CORS。这就是为什么
_client.extraHeaders = WEBSOCKETS_STRING("");
在您当地的图书馆。
研究了好几个小时 :D