ESP32 Websocket for client device orientation

Hello, I am seeking some guidance on a project I'm working on using the ESP32 S3 Sense camera board. I am fairly confident in the C++ side of things, but this project has taken me into the HTML and javascript that I am much less familiar with. The goal is to connect to the ESP32 as an access point from a phone and then to use the client's device orientation events from the phone as feedback to the ESP32.

I have successfully connected and used the ESP32 as a webserver using buttons programmed on the page to send feedback. This is what all of the examples I've found in my searches do (turn on/off an LED, motor, etc). Now I'd like to take things to the next stage using the device orientation.

I tested that the browser (Chrome) on my android device supports using device orientation using this test page and everything worked as expected.

To send the client orientation data to the ESP32 I used one of the websocket examples out there and modified below:

#include <WiFi.h> 
#include <WebServer.h>                                
#include <WebSocketsServer.h>
#include <ArduinoJson.h>

// SSID and password of Wifi connection:
const char* ssid = "ESP32";
const char* password = "PASSWORD";

// The string is the HTML for the page to be displayed
String webpage = "<!DOCTYPE html><html><head> <title>Device Orientation</title></head><body> <h1>Device Orientation</h1> <p>Move your device to see the orientation data.</p><script> var Socket; if(window.DeviceOrientationEvent) { window.addEventListener('deviceorientation', function(event) { var orientationData = { alpha: event.alpha, beta: event.beta, gamma: event.gamma }; Socket.send(JSON.stringify(orientationData));} } window.onload = function(event) { Socket = new WebSocket('ws://' + window.location.hostname + ':81/'); }</script></body></html>";

// Initialization of webserver and websocket
WebServer server(80);                                
WebSocketsServer webSocket = WebSocketsServer(81); 

void setup() {
  Serial.begin(115200);
 
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: http://");
  Serial.println(IP);
  
  server.on("/", []() { 
    server.send(200, "text/html", webpage);
  });
  server.begin();
  
  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

void loop() {
  server.handleClient(); 
  webSocket.loop();
}

void webSocketEvent(byte num, WStype_t type, uint8_t * payload, size_t length) {  
  switch (type) {                                     // switch on the type of information sent
    case WStype_DISCONNECTED:                         // if a client is disconnected, then type == WStype_DISCONNECTED
      Serial.println("Client " + String(num) + " disconnected");
      break;
    case WStype_CONNECTED:                            // if a client is connected, then type == WStype_CONNECTED
      Serial.println("Client " + String(num) + " connected");
      // optionally you can add code here what to do when connected
      break;
    case WStype_TEXT:                                 // if a client has sent data, then type == WStype_TEXT
      // try to decipher the JSON string received
      StaticJsonDocument<200> doc;                    // create a JSON container
      DeserializationError error = deserializeJson(doc, payload);
      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return;
      }
      else {
        // JSON string was received correctly, so information can be retrieved:
        const char* orientation_alpha = doc["alpha"];
        const char* orientation_beta = doc["beta"];
        const char* orientation_gamma = doc["gamma"];
        Serial.print("Alpha = " + String(orientation_alpha) + "\t");
        Serial.print("Beta = " + String(orientation_beta) + "\t");
        Serial.println("Gamma = " + String(orientation_gamma));
      }
      break;
  }
}

Since the HTML string in the code is hard to read I've got it here:

<!DOCTYPE html>
<html>
<head>
    <title>Device Orientation</title>
</head>
<body>
    <h1>Device Orientation</h1>
    <p>Move your device to see the orientation data.</p>
<script>
  var Socket;
  if(window.DeviceOrientationEvent) {
        window.addEventListener('deviceorientation', function(event) {
            var orientationData = {
                alpha: event.alpha,
                beta: event.beta,
                gamma: event.gamma
            };
            Socket.send(JSON.stringify(orientationData));
		}
  }
  window.onload = function(event) {
    Socket = new WebSocket('ws://' + window.location.hostname + ':81/');
  }
</script>
</body>
</html>

I can connect to the page as usual, but no data coming back on the serial monitor. To try and figure out which end the issue was on, I used the source code for the test page linked above and had the ESP32 serve that page. Again, I could connect, but the boxes where the data is to be displayed were all blank. It appears the issue is on the HTML javascript side of things. Can someone help me with this issue?

I would just try to see if you are getting communication from the browser to the esp32 at first.
Maybe send a msg from the browser to the esp32 after connecting to see if that works. At first glance the code looks good.

I appreciate your thoughts. I went back to the original websocket example sketch that I started from and kept adding to it until it broke. In the original, the ESP32 sends 2 random numbers every second to the socket which are displayed on the page. The button sends a string back to the server, displayed on the serial monitor. This works until I change the string to send back with the click of the button. By changing 'msg' to 'orientationData' in the HTML below, the page no longer displays the random numbers and the button does nothing.

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body style='background-color: #EEEEEE;'>

<span style='color: #003366;'>

<h1>Lets generate a random number</h1>
<p>The first random number is: <span id='rand1'>-</span></p>
<p>The second random number is: <span id='rand2'>-</span></p>
<p><button type='button' id='BTN_SEND_BACK'>
Send info to ESP32
</button></p>

</span>

</body>
<script>
  var Socket;
  document.getElementById('BTN_SEND_BACK').addEventListener('click', button_send_back);
  if(window.DeviceOrientationEvent) {
	window.addEventListener('deviceorientation', onOrientation(event));
  }
  function init() {
    Socket = new WebSocket('ws://' + window.location.hostname + ':81/');
    Socket.onmessage = function(event) {
      processCommand(event);
    };
  }
  function onOrientation(event) {
	var orientationData = {
		alpha: event.alpha,
		beta: event.beta,
		gamma: event.gamma
    };
  }
  function button_send_back() {
    var msg = {
		brand: 'Gibson',
		type: 'Les Paul Studio',
		year:  2010,
		color: 'white'
	};
	Socket.send(JSON.stringify(msg));
  }
  function processCommand(event) {
	var obj = JSON.parse(event.data);
	document.getElementById('rand1').innerHTML = obj.rand1;
	document.getElementById('rand2').innerHTML = obj.rand2;
    console.log(obj.rand1);
	console.log(obj.rand2);
  }
  window.onload = function(event) {
    init();
  }
</script>
</html>

Where did you get that library? Please post a GitHub link.

The websockets library was used in the example sketch I started from, so I went with it. The GitHub for it is here. I appreciate your help with this.

Which example? This One?
I don't see the sending of 2 random number every second as you mentioned.

Reading MDN docs it says device orientation event is only available in secure https environment so it may be its not working since your using http://

mdn link

This is the example I was using to start from to learn about websockets.

Awesome! This might be it. Can you tell me how to change it to use HTTPS? I will dig into it further as well.

That's the library's main GitHub page, not one of it's examples. Please provide a link to the exact example you started with as a guide.
Thanks!

This is the sketch I started from.

I really can't tell you except that I believe you need certificates to verify the server that you are contacting. It's above my pay grade.

What I normally do is use a reverse proxy like caddyfile that takes care all that secure https;
stuff. Its a black box to me but I have successfully got to access the esp32 camera over the internet by using it.

I watched Mo Thunders series on websockets also. It opens up a lot of possiblilities with the esp32. It prompted me to learn html, css and javascript. Still on that journey. Java script is hard to learn there is so much to it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.