当前位置: 首页 > 知识库问答 >
问题:

消息格式webSocket(Arduino Esp8266)

潘嘉佑
2023-03-14

更新几乎在那里,我可以收到消息,我想。当代码可读时,我会把它放进去。也在尝试发送。。

原始问题

我试图连接我的esp8266(@38400波特)(3.5美元的wifi芯片:)),到一个网络插座。该芯片与Arduino pro mini相连。这个设置是确定的,它的工作原理。

多亏了一些代码,我能握手了(https://github.com/ejeklint/ArduinoWebsocketServer).

这就是程序必须做的:

  • 握握手
  • 接收消息收到一些未知字符
  • 发送(当我能够接收时,我将了解如何发送)

我正在测试webSocket:http://www.websocket.org/echo.html

连接我的wifi模块ws://192.168.1.104:8000

当我向我的Arduino发送3 x信息“aaaa”时,我收到以下信息:

IPD,0,10: | | | q||b|k||c|||

知识产权署,0,10:| | | | | | | 0 | P | | | Q | 1|

IPD,0,10:| | | |Ӛ|±||

我怎样才能破译这个?

#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;
}

共有3个答案

狄玮
2023-03-14

您看到的是与HTTP头连接的第一个Web套接字框架(| | | | | q | | b | k | | c | |)。(IPD,0,10:)使用管道(|)进行定界的数据是不可理解的,因为它不是ASCII,也不是UTF8。必须将最后一个冒号(:)后面的数据显示为二进制。那么它应该是完全有意义的。我也在做同样的事情。只有当我把总数据显示为二进制时,我才“得到了”。我使用的是网络上的“网络套接字摇滚”演示。这是一个回音,它只会将“Web Sockets rock”发送到您指定的服务器。我把服务器地址改成了我的ESP8266的IP地址,然后开始查看帧。我为自己做了一点分析(和你一样),看看成功握手后ESP8266会返回什么。(我先学会了握手)下面是TeraTerm的“握手后”列表-

+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

字段的描述-(从冒号后的第一个字节开始。81)

// 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.
百里鸿祯
2023-03-14

我现在可以从网络插座发送信息了

boolean 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;
}

看https://github.com/zoutepopcorn/esp8266-Websocket/blob/master/arduino_websocket.ino

现在唯一的问题是arduino的websocket格式

萧丁雨
2023-03-14

我没有网络套接字的经验,但我认为网络套接字使用UTF-8,而Arduino终端使用ASCII。我在你的代码中没有看到UTF-8和ASCII之间的转换。

 类似资料:
  • 消息通常按照批量的方式写入.record batch 是批量消息的技术术语,它包含一条或多条 records.不良情况下, record batch 只包含一条 record.Record batches 和 records 都有他们自己的 headers.在 kafka 0.11.0及后续版本中(消息格式的版本为 v2 或者 magic=2)解释了每种消息格式.点击查看消息格式详情. 5.3.1

  • 我刚刚开始使用使用Apache Camel 2.15.3的应用程序。我是Camel的新手,我正在尝试了解消息是如何发送的,以及路由中组件之间的外观。 应用程序中的路由是使用Spring扩展xml设置的。以下是其中一条路由的示例。 首先是一个简短的术语问题:本示例中的中间bean叫什么?endpoint?组件?还是别的什么?现在我把它们叫做组件。 我现在的主要困惑是理解什么是输入,什么是从一个组件传

  • 1.1.1. 目录 1.1.2. 若琪智能家居协议 1.1.3. 示例 1.1.1. 目录 若琪智能家居协议 请求消息类型 回复消息类型 消息体 示例 一个控制请求 一个控制成功的返回 当发生了错误时的一个返回 1.1.2. 若琪智能家居协议 请求消息类型 命令 Directives 由若琪主动向 Skill 发起的请求,可以是 Skill 开放的 HTTP 服务,或者是 JSON RPC ove

  • 如何格式化WhatsApp Web消息?我试图替换这样的标签: 我试着使用urlencode、htmlspecialchars,什么都没有。 我收到https://api.whatsapp.com/send?phone=XXX

  • 问题内容: JSON.stringify显然不是非常节省空间。例如,当[123456789,123456789]可能需要大约5个字节时,它将占用20+字节。websocket是否在发送到流之前压缩其JSON? 问题答案: 从本质上讲,WebSocket只是用于TEXT或BINARY数据的一组框架。 它本身不执行压缩。 但是,WebSocket规范允许扩展,并且野外有各种各样的压缩扩展(其中一项的正

  • 我有一个来捕获可能发生的: 这里是有问题的对象: 如果在和中发送以下JSON正文: 如何处理在websocket消息上引发的?