#websocket #server #iot #esp8266 #stm32f0
Вопрос:
Я работаю над небольшим проектом интернета вещей на микроконтроллере STM32F070, подключенном к модулю Wi-Fi ESP8266. Я разработал клиентское приложение Websocket на контроллере STM32F070, которое будет взаимодействовать с удаленным сервером Websocket и обмениваться данными по соединению.
Я устанавливаю TCP-соединение с сервером от клиента Websocket, но после отправки заголовков запроса Websocket я получаю HTTP/1.1 400 Неверный запрос от сервера, и соединение ЗАКРЫВАЕТСЯ.
Вот журналы из линии ESP8266 UART:
ready
WIFI CONNECTED
WIFI GOT IP
AT
OK
ATE0
OK
OK
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IP
OK
CIFSR:STAIP,"192.168.43.194"
CIFSR:STAMAC,"48:3f:da:66:cf:2c"
OK
OK
ERROR
CLOSED
ERROR
CLOSED
CONNECT
OK
OK
>
Recv 227 bytes
SEND OK
IPD,103:HTTP/1.1 400 Bad Request
Connection: close
Content-Type: text/html
Content-Length: 11
Bad RequestCLOSED
Вот заголовки, которые я отправляю на удаленный сервер Websocket
AT RST
AT
ATE0
AT CWMODE=1
AT CWJAP="Txxxxx","08080808"
AT CIFSR
AT CIPMUX=0
AT CIPSTART="TCP","192.168.43.69",8080
AT CIPSEND=227
GET / HTTP/1.1
Host: 192.168.43.69:8080
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: NhEEf0jUzTLT3ZC2jSW1PnsX
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
ИЗМЕНИТЬ: Исходный код STM32F070 для отправки заголовков Websocket на сервер через ESP8266
// 1) Generating WebSocket Header:
//Generate a random key.
Base64_GetRandomKey( webSock.LocalKey );
//Reset the flag so we can check in response.
webSock.ServerKeyOK = 0;
//Host IP:
ip3 = ( dev.NetServerIP_Addr >> 24 ) amp; 0xFF;
ip2 = ( dev.NetServerIP_Addr >> 16 ) amp; 0xFF;
ip1 = ( dev.NetServerIP_Addr >> 8 ) amp; 0xFF;
ip0 = ( dev.NetServerIP_Addr ) amp; 0xFF;
//Make the HTML headers.
len = snprintf( amp;buf[len], HTTP_BUFFER_LEN_MAX - len, ( HTTP_PAGE_QUERY_REM_SRV_GET_HDR ), ip3, ip2, ip1, ip0, dev.NetServerPort );
len = snprintf( amp;buf[len], HTTP_BUFFER_LEN_MAX - len, ( HTTP_PAGE_QUERY_REM_SRV_GET_BODY ), webSock.LocalKey );
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 2) Send Data Header to ESP8266, send Data Length with AT CIPSEND AT Command
//Send the IP data header during data send.
static void ESP8266_SendDataHeader( ESP_Con *connection )
{
char buf[64];
sprintf( buf, "AT CIPSEND=%drn", connection->IPD_Len );
Esp8266TransmitWith( buf );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 3) Send Data after getting '>' char from ESP8266
//Wait for the data prompt.
len = FIFO2_GetCharsUntil( amp;espUsart.rxFIFO, esp.buffer, ESP_DATA_BUFFER_LEN, '>' );
if( len > 0 amp;amp; strstr( esp.buffer, ( ">" ) ) != NULL ) //Got the prompt to send data.
{
esp.timeout = EspConnectionTimeOutMed;
FIFO2_Flush(amp;espUsart.rxFIFO, 0 );
esp.state = EspStateSendDataReady;
}
else if( esp.timeout > ESP_TASK_INTERVAL )
{
esp.timeout -= ESP_TASK_INTERVAL;
}
else if( esp.retry > ESP_SEND_DATA_RETRY_MAX )
{
esp.state = EspStateIpClose;
}
else
{
esp.state = EspStateSendData;
// Sending Header Data to ESP8266 from Here
}
HTTP Headers from Source Code:
"GET / HTTP/1.1rnHost: %d.%d.%d.%d:%drn"
"Connection: Upgradern"
"Upgrade: websocketrn"
"Sec-WebSocket-Version: 13rn"
"Sec-WebSocket-Key: %srn"
"Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bitsrnrn"
Here is WebSocket Server Code in Node Js.
var bodyParser = require("body-parser");
const express = require('express'); //express framework to have a higher level of methods
const app = express(); //assign app variable the express class/method
var http = require('http');
var path = require("path");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const server = http.createServer(app);//create a server
//***************this snippet gets the local ip of the node.js server. copy this ip to the client side code and add ':3000' *****
//****************exmpl. 192.168.56.1---> var sock =new WebSocket("ws://192.168.56.1:3000");*************************************
require('dns').lookup(require('os').hostname(), function (err, add, fam) {
console.log('addr: ' add);
})
/**********************websocket setup**************************************************************************************/
//var expressWs = require('express-ws')(app,server);
const WebSocket = require('ws');
const s = new WebSocket.Server({ server });
s.on('connection', function(ws, req) {
console.log(req.headers);
console.log(req.params);
});
//when browser sends get request, send html file to browser
// viewed at http://localhost:30000
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname '/index.html'));
});
//*************************************************************************************************************************
//***************************ws chat server********************************************************************************
//app.ws('/echo', function(ws, req) {
s.on('connection',function(ws,req){
/******* when server receives messsage from client trigger function with argument message *****/
ws.on('message',function(message){
console.log("Received: " message);
s.clients.forEach(function(client){ //broadcast incoming message to all clients (s.clients)
if(client!=ws amp;amp; client.readyState ){ //except to the same client (ws) that sent this message
client.send("broadcast: " message);
}
});
// ws.send("From Server only to sender: " message); //send to client where message is from
});
ws.on('close', function(){
console.log("lost one client");
});
//ws.send("new client connected");
console.log("new client connected");
});
server.listen(8080);
Сервер NodeJS WebSocket тестируется с помощью мобильного приложения WebSocketClient Tester для Android. Он отлично работает
ПРАВКА 2:
Я попытался подключиться http://echo.websocket.org/, Я изменил код для подключения к http://echo.websocket.org/. Я могу успешно связаться с http://echo.websocket.org/. Получен ответ от http://echo.websocket.org/
вот журналы для справки.
чтобы http://echo.websocket.org/
GET / HTTP/1.1
Host: echo.websocket.org
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: Dh6EV0ZUpTBTtZ42ZSM1FniX
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
IPD,201:HTTP/1.1 101 Web Socket Protocol Handshake
Connection: Upgrade
Date: Sun, 23 May 2021 08:54:52 GMT
Sec-WebSocket-Accept: TaHsjyffJhTaBluq4Bmksq0NPWo=
Server: Kaazing Gateway
Upgrade: websocket
Комментарии:
1. у вас есть пустая строка после заголовков http?
2. Нет, после заголовков нет пустых строк.
3. протокол HTTP требует, чтобы после заголовков была пустая строка
4. ох, моя беда, после HTTP-заголовков есть пустая строка. Отредактированный вопрос
5. Опубликуйте свой код stm32, свой node.js код не имеет значения, если вы уже протестировали его с помощью приложения для Android.