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