消息格式websocket(Arduino+;Esp8266)
更新 我想我几乎可以在那里收到信息。当代码可读时,我将把它放进去。也在尝试发送 原始问题 我正在尝试将我的esp8266(@38400波特)(3.50美元wifi芯片:)连接到Websocket。该芯片与Arduino pro mini相连。此设置正常,可以正常工作 由于一些代码(),我能够进行握手 这就是程序必须做的:消息格式websocket(Arduino+;Esp8266),websocket,arduino,esp8266,Websocket,Arduino,Esp8266,更新 我想我几乎可以在那里收到信息。当代码可读时,我将把它放进去。也在尝试发送 原始问题 我正在尝试将我的esp8266(@38400波特)(3.50美元wifi芯片:)连接到Websocket。该芯片与Arduino pro mini相连。此设置正常,可以正常工作 由于一些代码(),我能够进行握手 这就是程序必须做的: 处理握手V 接收消息接收到一些未知字符 发送(当我能够接收时,我将了解如何发送) 我正在使用以下工具测试websocket: 连接我的wifi模块 ws://192.16
- 处理握手V
- 接收消息接收到一些未知字符
- 发送(当我能够接收时,我将了解如何发送)
#include "sha1.h"
#include "Base64.h"
#include <SoftwareSerial.h>
#include <MemoryFree.h>
SoftwareSerial debug(8, 9); // RX, TX
void setup() {
Serial.begin(38400);
debug.begin(38400);
delay(50);
debug.println("start");
Serial.println("AT+RST");
delay(5000);
Serial.println("AT+CWMODE=1"); // NO CHANGE
delay(1500);
Serial.find("OK");
Serial.println("AT+CIPMUX=1");
Serial.find("OK");
delay(3000);
Serial.println("AT+CIPSERVER=1,8000");
boolean server = Serial.find("OK");
delay(3000);
Serial.println("AT+CIFSR"); // Display the ip please
boolean r = readLines(4);
debug.println("eind setup");
debug.println(server);
boolean found = false;
while(!found) // wait for the link
found = Serial.find("Link");
debug.println("link builded, end setup");
}
void loop() {
String key = "";
boolean isKey = Serial.find("Key: ");
if(isKey) {
debug.println("Key found!");
while(true) {
if(Serial.available()) {
char c = (char)Serial.read();
if(c == '=') {
doHandshake(key + "==");
key = "";
break;
}
if(c != '\r' || c != '\n') {
key = key + c;
}
}
}
// _________________________ PROBLEMO ____________________________________
while(true) { // So far so good. Handshake done Now wait for the message
if(Serial.available()) {
char c = (char)Serial.read();
debug.print(c);
debug.print(" | ");
}
}
}
// _________________________ /PROBLEMO ____________________________________
}
boolean readLines(int lines) {
boolean found = false;
int count = 0;
while(count < lines) {
if(Serial.available()) {
char c = (char)Serial.read();
if(c != '\r') {
debug.write(c);
} else {
count++;
}
}
}
return true;
}
bool doHandshake(String k) {
debug.println("do handshake: " + k);
char bite;
char temp[128];
char key[80];
memset(temp, '\0', sizeof(temp));
memset(key, '\0', sizeof(key));
byte counter = 0;
int myCo = 0;
while ((bite = k.charAt(myCo++)) != 0) {
key[counter++] = bite;
}
strcat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); // Add the omni-valid GUID
Sha1.init();
Sha1.print(key);
uint8_t *hash = Sha1.result();
base64_encode(temp, (char*)hash, 20);
debug.print(temp);
int cc = -1;
while(temp[cc++] != '\0') {} // cc is length return key
cc = 165 + cc; // length return key + 165 keys for rest of header
Serial.print("AT+CIPSEND=0,");
Serial.println(129); // +30 // was 129
boolean found = false;
while(!found)
found = Serial.find(">"); // Wait until I can send
Serial.print("HTTP/1.1 101 Switching Protocols\r\n");
Serial.print("Upgrade: websocket\r\n");
Serial.print("Connection: Upgrade\r\n");
Serial.print("Sec-WebSocket-Accept: ");
Serial.print(temp);
Serial.print("\r\n\r\n");
return true;
}
#包括“sha1.h”
#包括“Base64.h”
#包括
#包括
软件串行调试(8,9);//接收,发送
无效设置(){
Serial.begin(38400);
调试开始(38400);
延迟(50);
println(“开始”);
序列号。打印号(“AT+RST”);
延迟(5000);
Serial.println(“AT+CWMODE=1”);//无更改
延迟(1500);
序列号。查找(“确定”);
Serial.println(“AT+CIPMUX=1”);
序列号。查找(“确定”);
延迟(3000);
Serial.println(“AT+CIPSERVER=18000”);
布尔服务器=Serial.find(“确定”);
延迟(3000);
Serial.println(“AT+CIFSR”);//请显示ip
布尔r=读线(4);
println(“eind设置”);
println(服务器);
布尔值=false;
while(!found)//等待链接
查找=串行。查找(“链接”);
println(“链接构建,结束设置”);
}
void循环(){
字符串键=”;
布尔值isKey=Serial.find(“Key:”);
如果(isKey){
println(“找到键!”);
while(true){
if(Serial.available()){
char c=(char)Serial.read();
如果(c=='='='){
握手(键+“=”);
key=“”;
打破
}
如果(c!='\r'| | c!='\n'){
键=键+c;
}
}
}
//问题____________________________________
while(true){//到目前为止还不错。现在握手完毕,等待消息
if(Serial.available()){
char c=(char)Serial.read();
调试、打印(c);
调试。打印(“|”);
}
}
}
//_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu/问题____________________________________
}
布尔读线(整型线){
布尔值=false;
整数计数=0;
while(计数<行){
if(Serial.available()){
char c=(char)Serial.read();
如果(c!='\r'){
debug.write(c);
}否则{
计数++;
}
}
}
返回true;
}
布尔握手(字符串k){
println(“做握手:+k”);
焦咬;
字符温度[128];
字符键[80];
memset(temp,'\0',sizeof(temp));
memset(键'\0',sizeof(键));
字节计数器=0;
int-myCo=0;
而((bite=k.charAt(myCo++)!=0){
键[计数器++]=咬合;
}
strcat(键,“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”);//添加全向有效GUID
Sha1.init();
Sha1.打印(键);
uint8_t*hash=Sha1.result();
base64_编码(temp,(char*)散列,20);
调试打印(临时);
int cc=-1;
而(temp[cc++]!='\0'){}//cc是长度返回键
cc=165+cc;//页眉剩余部分的长度返回键+165键
串行打印(“AT+CIPSEND=0,”);
Serial.println(129);//+30//was 129
布尔值=false;
而(!found)
found=Serial.find(“>”;//等待,直到我可以发送
串行打印(“HTTP/1.1 101交换协议\r\n”);
Serial.print(“升级:websocket\r\n”);
Serial.print(“连接:升级\r\n”);
串行打印(“Sec WebSocket接受:”);
串行打印(temp);
Serial.print(“\r\n\r\n”);
返回true;
}
我没有使用WebSocket的经验,但我认为WebSocket使用UTF-8,而Arduino终端使用ASCII。我在您的代码中没有看到UTF-8和ASCII之间的转换。我现在可以从websocket>>arduino发送消息。但是发送不起作用:(
boolean getFrame(){
println(“getFrame()”);
字节位;
无符号短有效负载长度=0;
bite=Serial.read();
frame.opcode=bite&0xf;//操作码
frame.isFinal=bite&0x80;//最终帧?
bite=Serial.read();
frame.length=bite&0x7f;//有效负载的长度
frame.ismask=bite&0x80;
//帧完成!
如果(!frame.isFinal){
返回false;
}
//首先检查框架尺寸是否在我们的限制范围内。
如果(frame.length>126){
返回false;
}
//如果标题的长度部分为126,则表示它包含扩展长度字段。
//接下来的两个字节包含实际有效负载大小,因此我们需要获得“真实”长度。
if(frame.length==126){
字节exLengthByte1=串行.read();
字节exLengthByte2=Serial.read();
payloadLength=(exLengthByte1最大接收消息大小){
debug.println(“te groot”);
返回false;
}
//客户端应始终发送掩码,但请检查以确保
if(frame.ismask){
frame.mask[0]=Serial.read();
frame.mask[1]=Serial.read();
frame.mask[2]=Serial.read();
frame.mask[3]=Serial.read();
}
//获取消息字节并在必要时取消它们的掩码
对于(int i=0;iboolean getFrame() {
debug.println("getFrame()");
byte bite;
unsigned short payloadLength = 0;
bite = Serial.read();
frame.opcode = bite & 0xf; // Opcode
frame.isFinal = bite & 0x80; // Final frame?
bite = Serial.read();
frame.length = bite & 0x7f; // Length of payload
frame.isMasked = bite & 0x80;
// Frame complete!
if (!frame.isFinal) {
return false;
}
// First check if the frame size is within our limits.
if (frame.length > 126) {
return false;
}
// If the length part of the header is 126, it means it contains an extended length field.
// Next two bytes contain the actual payload size, so we need to get the "true" length.
if (frame.length == 126) {
byte exLengthByte1 = Serial.read();
byte exLengthByte2 = Serial.read();
payloadLength = (exLengthByte1 << 8) + exLengthByte2;
}
// If frame length is less than 126, that is the size of the payload.
else {
payloadLength = frame.length;
}
// Check if our buffer can store the payload.
if (payloadLength > MAX_RECEIVE_MESSAGE_SIZE) {
debug.println("te groot");
return false;
}
// Client should always send mask, but check just to be sure
if (frame.isMasked) {
frame.mask[0] = Serial.read();
frame.mask[1] = Serial.read();
frame.mask[2] = Serial.read();
frame.mask[3] = Serial.read();
}
// Get message bytes and unmask them if necessary
for (int i = 0; i < payloadLength; i++) {
if (frame.isMasked) {
frame.data[i] = Serial.read() ^ frame.mask[i % 4];
} else {
frame.data[i] = Serial.read();
}
}
for (int i = 0; i < payloadLength; i++) {
debug.print(frame.data[i]);
if(frame.data[i] == '/r')
break;
}
return true;
}
// !!!!!!!!!! NOT WORKING
boolean sendMessage(char *data, byte length) {
Serial.print((uint8_t) 0x1); // Txt frame opcode
Serial.print((uint8_t) length); // Length of data
for (int i = 0; i < length ; i++) {
Serial.print(data[i]);
}
delay(1);
return true;
}
+IPD,0,21:r¨$v%ÍF%ËVÃW (NOTE: Garbage after the :)
0 2B 0010 1011
1 49 0100 1001
2 50 0101 0000
3 44 0100 0100
4 2C 0010 1100
5 30 0011 0000
6 2C 0010 1100
7 32 0011 0010 (Ascii for 21 bytes to follow)
8 31 0011 0001 (Ascii for 21 bytes to follow)
9 3A 0011 1010 (Colon)
10 -7F 1000 0001 (Start of actual FRAME)
11 -71 1000 1111
12 72 0111 0010
13 -58 1010 1000
14 24 0010 0100
15 76 0111 0110
16 25 0010 0101
17 -33 1100 1101
18 46 0100 0110
19 25 0010 0101
20 1D 0001 1101
21 -35 1100 1011
22 4F 0100 1111
23 13 0001 0011
24 6 0000 0110
25 -78 1000 1000
26 56 0101 0110
27 19 0001 1001
28 11 0001 0001
29 -3D 1100 0011
30 57 0101 0111
// First byte has FIN bit and frame type opcode = text
// Second byte mask and payload length
// next four bytes for masking key
// So total of 6 bytes for the overhead
// The size of the payload in this case is "F" = 15 (the 4th nibble)
// So total of bytes are (6+15) = 21
// The first byte is saying> FIN bit is set. This is last frame in sequence. The OP code is 1 = TEXT data.
// The second byte is saying> MASK bit is set. The following data will be masked. The data length is "F" = 15
// The 3rd, 4th, 5th, 6th bytes is the masking key. In this case 72, A8, 24, 76.