Simple ESP32 WebSocket client example?

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Simple ESP32 WebSocket client example?

Postby paulfer » Sun Oct 08, 2017 10:23 pm

HI Guys
I have been bashing my head all day with this sockets stuff.
What I would like is for someone to show me how to achieve a simple sockets app that has the ESP32 as a client and connecting to a server. BUT, here is my issue....gefore I show you how far I have got with the Arduino code, let me give you some background...

What I have, is a socket server running on my hosting service, and i have created a IIS app that consumes a socket request. I have it running smoothly if I use my browser to connect and send messages. Here is the javascript that essentially send the connect request from my browser to the server:

Code: Select all

var connection = new WebSocket("ws://" + location.host + "/chat/wsock.ashx?UN=" + yrname);
            connection.onmessage = function (message) {

                var data = window.JSON.parse(message.data);
                //alert(data.mBody);
                $("<li/>").html(data.mBody).appendTo($("#messages"));
            };
This works flawlessly from Chrome browser.

Now, what I amtrying to do is to connect to the same server, with the ESP32 and send the same querystring as above.

When I try this code on the ESP32, it works in that it doesnt fail, so I assume it has made the sockets connection. (But of course it sets no querystring):

Code: Select all

struct addrinfo hints, *res;
  int sockfd;
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  
  if (getaddrinfo("www.itbpaul.co.za", "80", &hints, &res))
  {
    Serial.println("fail at getaddrinfo");
  }

  // make a socket:
  if (
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  ) {
    Serial.println("fail at socket");
  }
  // connect!
  if (connect(sockfd, res->ai_addr, res->ai_addrlen))
  {
    Serial.println("no connect");
  }
BUT if I try anything crazy like inserting the querystring above it cause a system crash.

i Have also tried appending this to the end to no avail:

Code: Select all

char *msg = "GET ws://itbpaul.co.za/chat/wsock.ashx?UN=psdsd \n\n";
int len, bytes_sent;

len = strlen(msg);
bytes_sent = send(sockfd, msg, len, 0);
Serial.println("all ok");  
Serial.println(bytes_sent);
Help would be appreciated.

I have also read the following articles to try get more background but I am stuck:

https://www.youtube.com/watch?v=KyCZh9NcinI
http://www.tcpipguide.com/free/t_HTTPRe ... Format.htm
https://www.freebsd.org/doc/en_US.ISO88 ... tions.html
http://esp32.info/docs/esp_idf/html/d4/ ... ource.html
http://beej.us/guide/bgnet/output/print/bgnet_A4.pdf

Regards and thanks
Paul

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Re: Simple ESP32 Socket as a client example

Postby paulfer » Mon Oct 09, 2017 10:08 pm

I think I must have searched the entire web now...I cannot find a SINGLE example of an ESP32 acting as a websockets client.

This is what I have done so far and have had limited success:

To recap:

I have a asp iHttphandler residing within IIS. It waits for incoming socket requests and handles accordingly.

IF I change my code to the following where the message I send is a well formed GET request, the system logs me on and send back the switching to sockets:

Code: Select all

memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  if (getaddrinfo("www.rubotix.co.za", "80", &hints, &res))
  {
    Serial.println("failed at get addr info");
  }
  Serial.println("trying a socket...");
  // make a socket:
  if (
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  ) {
    Serial.println("failed at socket");
  }
  // connect!
  if (connect(sockfd, res->ai_addr, res->ai_addrlen))
  {
    Serial.println("nocconnect");
  }



  char *msg = "GET /sox/wsock.ashx?UN=ARDUINI HTTP/1.1\r\n"
              "Host: rubotix.co.za\r\n"
              "Connection: Upgrade\r\n"
              "Pragma: no-cache\r\n"
              "Cache-Control: no-cache\r\n"
              "Sec-WebSocket-Protocol: chat, superchat\r\n"
              "Upgrade: websocket\r\n"
              "Sec-WebSocket-Version: 13\r\n"
              "Accept-Encoding: gzip, deflate\r\n"
              "Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,es;q=0.4\r\n"
              "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
              "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n";

  int len, bytes_sent;

  len = strlen(msg);
  bytes_sent = send(sockfd, msg, len, 0);
  Serial.println("all ok");  Serial.println(bytes_sent);
}

void loop() {
  delay(5000);
  char *msg = "{\"mBody\":\"Hello there daddy bear\"}";
  Serial.println(msg);
  int len, bytes_sent;

  len = strlen(msg) + 1;
  bytes_sent = send(sockfd, msg, len, 0);
  Serial.println("all ok");  Serial.println(bytes_sent);
  if (bytes_sent < 0)
  {
    Serial.print("err:");
    Serial.println(errno);
  }
}
BUT, once the loop starts and I try to send some data back to the server, the system err's with the 104 error of 'Connection Reset By Peer'

So, quo vadis?????? How do I get the messages up to the server after logon?

Regards
Paul

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Re: Simple ESP32 Socket as a client example

Postby paulfer » Wed Oct 11, 2017 1:10 am

I finally got a library that works and have got it working fine now.

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Re: Simple ESP32 WebSocket client example?

Postby paulfer » Thu Oct 12, 2017 2:04 pm

Hi Guys, for what its worth, here is my code. It communciates with my server just fine. Now I just have to work out how to do this in SSL. :lol:

Code: Select all

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebSocketClient.h>
#include <Preferences.h>

//eeprom
Preferences pref;


byte mac[6];
char macaddress[30];

WebSocketClient webSocketClient;

// Use WiFiClient class to create TCP connections
WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(10);

  //start eeprom
  pref.begin("xxx", false);
  delay(10);
  
  // We start by connecting to a WiFi network
  //get password and username from eeprom
  String pwd = pref.getString("pw", "xxx");
  int i = pwd.length() + 1;
  char password[i];
  pwd.toCharArray(password, i);
  String ssi = pref.getString("ssid", "xxx");
  i = ssi.length() + 1;
  char ssid[i];
  ssi.toCharArray(ssid, i);
  //get host from eeprom
  String eehos = pref.getString("eehost", "xxx.co.za");
  i = eehos.length() + 1;
  char eehost[i];
  eehos.toCharArray(eehost, i);
  //get path to websockets from eeprom
  String eepat = pref.getString("eepath", "/xxx/xxx.ashx?UN=");
  i = eepat.length() + 1;
  char eepath[i];
  eepat.toCharArray(eepath, i);

  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  delay(1000);

  //get the mac address of the Magafter
  WiFi.macAddress(mac);


  // Connect to the websocket server
  if (client.connect(eehost, 80)) {
    Serial.println("xxx Connected");
  } else {
    Serial.println("xxx Connection failed.");
    while (1) {
      // Hang on failure
    }
  }

  char path[50];
  memset(path, 0, sizeof(path));

  strcpy(path, eepath);
  
  //turn the mac array into a char array with separators
  memset(macaddress, 0, sizeof(macaddress));

  char result[5];
  for (int i = 0; i < 6; i++)
  {
    memset(result, 0, sizeof(result));
    sprintf(result, "%x", (char)mac[i]);
    //macaddress[i] = (char)mac[i];
    strcat(macaddress, result);
    strcat(macaddress, "-");
  }

  strcat(path, macaddress);

  // Handshake with the server
  webSocketClient.path = path;
  webSocketClient.host = eehost;
  if (webSocketClient.handshake(client)) {
    Serial.println("Handshake successful");
  } else {
    Serial.println("Handshake failed.");
    while (1) {
      // Hang on failure
    }
  }


}

String data;

void loop() {
  data = "";

  //esp_task_wdt_feed(); so much for watchdogs :-(

  if (client.connected()) {

    webSocketClient.getData(data);
    if (data.length() > 0) {
      Serial.print("Received data: ");
      Serial.println(data);
      if (data.indexOf("#qq") > -1)
      {
      //just silly test stuff
        String sdata = "{\"mBody\":\"Status is-" + String(millis()) + "\",\"mUser\":\"" + macaddress + "\"}" ;
        webSocketClient.sendData(sdata);
      }
      if (data.indexOf("#gdc") > -1)
      {
        String sdata = "{\"mBody\":\"Garage Door Close-" + String(millis()) + "\",\"mUser\":\"" + macaddress + "\"}" ;
        webSocketClient.sendData(sdata);
      }
    }



  } else {
    Serial.println("Client disconnected. Restarting system...");
    delay(2000);
    esp_restart(); //testing the restart command more than anything else
  }

 delay(1000);

}

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Re: Simple ESP32 WebSocket client example?

Postby paulfer » Thu Oct 12, 2017 2:10 pm


Edd_III
Posts: 1
Joined: Sun Oct 22, 2017 8:12 pm

Re: Simple ESP32 WebSocket client example?

Postby Edd_III » Sun Oct 22, 2017 8:18 pm

Do You make some changes to this library?
i try use it in same way but take errors from compiler ...

paulfer
Posts: 6
Joined: Sun Oct 08, 2017 10:07 pm

Re: Simple ESP32 WebSocket client example?

Postby paulfer » Sun Oct 22, 2017 10:34 pm

HI Yes, I had to comment out some of the duplicate references. If i remember correctly it was for SHA and Hash references in header files.

ajw685
Posts: 1
Joined: Sun Oct 29, 2017 4:50 am

Re: Simple ESP32 WebSocket client example?

Postby ajw685 » Sun Oct 29, 2017 4:55 am

To get my Arduino IDE to compile using ESP8266-Websocket, I changed:

*Arduino\libraries\ESP8266-Websocket\MD5.h
-Line 30
from "void MD5Init (MD5_CTX *);"
to "void MD5InitXXX (MD5_CTX *);"
-Line 31
from "void MD5Update (MD5_CTX *, unsigned char *, unsigned int);"
to "void MD5UpdateXXX (MD5_CTX *, unsigned char *, unsigned int);"
-Line 32
from "void MD5Final (unsigned char [16], MD5_CTX *);"
to "void MD5FinalXXX (unsigned char [16], MD5_CTX *);"

*Arduino\libraries\ESP8266-Websocket\MD5.c
-Line 92
from "void MD5Init (MD5_CTX *context)"
to "void MD5InitXXX (MD5_CTX *context)"
-Line 106
from "void MD5Update (MD5_CTX *context, unsigned char *input,unsigned int inputLen)"
to "void MD5UpdateXXX (MD5_CTX *context, unsigned char *input,unsigned int inputLen)"
-Line 139
from "void MD5Final (unsigned char digest[16], MD5_CTX *context)"
to "void MD5FinalXXX (unsigned char digest[16], MD5_CTX *context)"

Who is online

Users browsing this forum: PeterMenkveld and 5 guests