[SOLVED] How should I use AJAX with ESP32 ?

GeorgeFlorian1
Posts: 160
Joined: Thu Jan 31, 2019 2:32 pm

[SOLVED] How should I use AJAX with ESP32 ?

Postby GeorgeFlorian1 » Wed Mar 20, 2019 3:29 pm

Hello !

The idea behind my project is to send made-by-hand logs to a webpage so that I don't have to rely solely on the Serial Monitor.
I am trying to send Strings from ESP32 to a webpage that is hosted by the same ESP32.
I am using a circular buffer so that I don't end up using all the memory.

I googled how should I refresh a div inside a html but my code does not work.
I have no knowledge about JS, jQuery or AJAX, and I find it very hard to understand, especially when I have to use it with the ESP, which I've begun learning about 2 months ago.

This is the main.cpp

Code: Select all

#include <Arduino.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <cstdio>
#include <memory>
#include <mutex>

void logOutput(String string);

template <class T>
class circular_buffer {
public:
	explicit circular_buffer(size_t size) :
		buf_(std::unique_ptr<T[]>(new T[size])),
		max_size_(size)
	{

	}

	void put(T item){
		std::lock_guard<std::mutex> lock(mutex_);

		buf_[head_] = item;

		if(full_){
			tail_ = (tail_ + 1) % max_size_;
		}
		head_ = (head_ + 1) % max_size_;
		full_ = head_ == tail_;
	}

	T get()	{
		std::lock_guard<std::mutex> lock(mutex_);

		if(empty())	{
			return T();
		}
		//Read data and advance the tail (we now have a free space)
		auto val = buf_[tail_];
		full_ = false;
		tail_ = (tail_ + 1) % max_size_;

		return val;
	}

	T get2() {
		std::lock_guard<std::mutex> lock(mutex_);
		if(empty())	{
			return T();
		}
		auto val = buf_[tail_];
		return val;
	}

	void reset() {
		std::lock_guard<std::mutex> lock(mutex_);
		head_ = tail_;
		full_ = false;
	}

	bool empty() const {
		//if head and tail are equal, we are empty
		return (!full_ && (head_ == tail_));
	}

	bool full() const	{
		//If tail is ahead the head by 1, we are full
		return full_;
	}

	size_t capacity() const	{
		return max_size_;
	}

	size_t size() const	{
		size_t size = max_size_;

		if(!full_)	{
			if(head_ >= tail_)	{
				size = head_ - tail_;
			} else {
				size = max_size_ + head_ - tail_;
			}
		}
		return size;
	}

private:
	std::mutex mutex_;
	std::unique_ptr<T[]> buf_;
	size_t head_ = 0;
	size_t tail_ = 0;
	const size_t max_size_;
	bool full_ = 0;
};

circular_buffer<String> circle(20);

void logOutput(String string) {
	delay(2000);
	circle.put(string);
	Serial.println(string);	
}

AsyncWebServer server(80);

const char* ssid = "ssid";
const char* password = "password";

String processor(const String& var) { 
		   if(var == "PLACEHOLDER_1"){
		return circle.get();
	} else if(var == "PLACEHOLDER_2") {
		return circle.get();
	} else if(var == "PLACEHOLDER_3") {
		return circle.get();
	} else if(var == "PLACEHOLDER_4") {
		return circle.get();
	} else if(var == "PLACEHOLDER_5") {
		return circle.get();
	}
	return String();
}

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

	if(!SPIFFS.begin(true)) {
		logOutput("ERROR ! SPIFFS file system was not mounted. Reformatting !");
	}

	WiFi.begin(ssid, password);
	delay(1000);
	int k = 0;
	while(WiFi.status() != WL_CONNECTED && k<20) {
		delay(1000);
		k++;
		logOutput("Connecting to WiFi");
	}
	if(WiFi.status() == WL_CONNECTED) {
		logOutput((String)"Connected to: " + ssid + " with IP: " + WiFi.localIP().toString());
	} else {
		logOutput("Couldn't connect to WiFi ! Restarting in 5 seconds");
		delay(5000);
		ESP.restart();
	}

	server.on("/logs", HTTP_GET, [](AsyncWebServerRequest* request){
		request->send(SPIFFS, "/events.html", "text/html", false, processor);
	});
	server.on("/master.css", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/master.css", "text/css");
	});	
	server.on("/back-image.jpg", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/back-image.jpg", "image/jpeg");
	});
	server.on("/logo.png", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/logo.png", "image/png");
	});

	server.begin();
	delay(5000);

	logOutput("After server.begin()");
	for(int i = 1; i<=10;i++){
		logOutput((String)"Linia " + i);
	}
}

void loop() {
	logOutput("Beginning the loop()");
	logOutput("\n");
	delay(10000);
}
This is the events.html

Code: Select all

<!DOCTYPE html>
<html>    
<head>
    <meta charset = "utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <link rel = "stylesheet" type = "text/css" href = "master.css">   
    <title>Events Log</title>
<script type="text/javascript" src="jquery-1.9.0.min.js"></script>
<script>
$(document).ready( function(){
$('#big-box').load('events.html');
refresh();
});
 
function refresh()
{
	setTimeout( function() {
	  $('#big-box').fadeOut('slow').load('events.html').fadeIn('slow');
	  refresh();
	}, 2000);
}
</script>
</head>


<body onload="startTime()">
    <div id="big-box">
        <div class="textbox">%PLACEHOLDER_1%</div>
        <div class="textbox">%PLACEHOLDER_2%</div>
        <div class="textbox">%PLACEHOLDER_3%</div>
        <div class="textbox">%PLACEHOLDER_4%</div>
        <div class="textbox">%PLACEHOLDER_5%</div>
    </div>

</body>
Last edited by GeorgeFlorian1 on Thu Mar 21, 2019 11:37 am, edited 1 time in total.

GeorgeFlorian1
Posts: 160
Joined: Thu Jan 31, 2019 2:32 pm

Re: How should I use AJAX with ESP32 ?

Postby GeorgeFlorian1 » Thu Mar 21, 2019 11:37 am

With help, I've fixed it !

There were a few problems in my code:
  • $('#big-box').load('events.html') actually loads another file (in my case events.html) that, besides coinciding with an existing .html, the /events.html path wasn't handled properly by the ESP32 server.
  • <script type="text/javascript" src="jquery-1.9.0.min.js"></script> tries loading a source file that isn't there.
So I made some changes:
  1. I made another .html file and named it events_log.html and added what I actually wanted to be refreshed. In my case, the 5 divs containing &PLACEHOLDERS& then uploaded it into the ESP32
  2. I changed $('#big-box').load('events.html') to $('#big-box').load('events_log.html')
  3. I changed $('#big-box').fadeOut('slow').load('events.html').fadeIn('slow'); to $('#big-box').fadeOut('slow').load('events_log.html').fadeIn('slow');
  4. I made a jquery-1.12.4.min.js file containing what's in this link and uploaded it in the ESP
  5. Changed <script type="text/javascript" src="jquery-1.9.0.min.js"></script> to <script type="text/javascript" src="jquery-1.12.4.min.js"></script>
  6. Made proper path handlers to events_log.html and jquery-1.12.4.min.js in the ESP32 code:

    Code: Select all

    	server.on("/events_log.html", HTTP_GET, [](AsyncWebServerRequest* request){
    		request->send(SPIFFS, "/events_log.html", "text/html", false, processor);
    	});
    	server.on("/jquery-1.12.4.min.js", HTTP_GET, [](AsyncWebServerRequest* request){
    		request->send(SPIFFS, "/jquery-1.12.4.min.js", "text/javascript");
    	});	
    
main.cpp

Code: Select all

#include <Arduino.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <cstdio>
#include <memory>
#include <mutex>

void logOutput(String string);


//---------- Circular Buffer
template <class T>
class circular_buffer {
public:
	explicit circular_buffer(size_t size) :
		buf_(std::unique_ptr<T[]>(new T[size])),
		max_size_(size)
	{

	}

	void put(T item){
		std::lock_guard<std::mutex> lock(mutex_);

		buf_[head_] = item;

		if(full_){
			tail_ = (tail_ + 1) % max_size_;
		}
		head_ = (head_ + 1) % max_size_;
		full_ = head_ == tail_;
	}

	T get()	{
		std::lock_guard<std::mutex> lock(mutex_);

		if(empty())	{
			return T();
		}
		//Read data and advance the tail (we now have a free space)
		auto val = buf_[tail_];
		full_ = false;
		tail_ = (tail_ + 1) % max_size_;

		return val;
	}

	T get2() {
		std::lock_guard<std::mutex> lock(mutex_);
		if(empty())	{
			return T();
		}
		auto val = buf_[tail_];
		return val;
	}

	void reset() {
		std::lock_guard<std::mutex> lock(mutex_);
		head_ = tail_;
		full_ = false;
	}

	bool empty() const {
		//if head and tail are equal, we are empty
		return (!full_ && (head_ == tail_));
	}

	bool full() const	{
		//If tail is ahead the head by 1, we are full
		return full_;
	}

	size_t capacity() const	{
		return max_size_;
	}

	size_t size() const	{
		size_t size = max_size_;

		if(!full_)	{
			if(head_ >= tail_)	{
				size = head_ - tail_;
			} else {
				size = max_size_ + head_ - tail_;
			}
		}
		return size;
	}

private:
	std::mutex mutex_;
	std::unique_ptr<T[]> buf_;
	size_t head_ = 0;
	size_t tail_ = 0;
	const size_t max_size_;
	bool full_ = 0;
}; //---------- Circular Buffer

circular_buffer<String> circle(20);

void logOutput(String string) {
	delay(2000);
	circle.put(string);
	Serial.println(string);	
}

AsyncWebServer server(80);

const char* ssid = "ssid";
const char* password = "password";

String processor(const String& var) { 
		   if(var == "PLACEHOLDER_1"){
		return circle.get();
	} else if(var == "PLACEHOLDER_2") {
		return circle.get();
	} else if(var == "PLACEHOLDER_3") {
		return circle.get();
	} else if(var == "PLACEHOLDER_4") {
		return circle.get();
	} else if(var == "PLACEHOLDER_5") {
		return circle.get();
	}
	return String();
}

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

	if(!SPIFFS.begin(true)) {
		logOutput("ERROR ! SPIFFS file system was not mounted. Reformatting !");
	}

	WiFi.begin(ssid, password);
	delay(1000);
	int k = 0;
	while(WiFi.status() != WL_CONNECTED && k<20) {
		delay(1000);
		k++;
		logOutput("Connecting to WiFi");
	}
	if(WiFi.status() == WL_CONNECTED) {
		logOutput((String)"Connected to: " + ssid + " with IP: " + WiFi.localIP().toString());
	} else {
		logOutput("Couldn't connect to WiFi ! Restarting in 5 seconds");
		delay(5000);
		ESP.restart();
	}

	server.on("/logs", HTTP_GET, [](AsyncWebServerRequest* request){
		request->send(SPIFFS, "/events.html", "text/html", false, processor);
	});
	server.on("/events_log.html", HTTP_GET, [](AsyncWebServerRequest* request){
		request->send(SPIFFS, "/events_log.html", "text/html", false, processor);
	});
	server.on("/jquery-1.12.4.min.js", HTTP_GET, [](AsyncWebServerRequest* request){
		request->send(SPIFFS, "/jquery-1.12.4.min.js", "text/javascript");
	});	
	server.on("/master.css", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/master.css", "text/css");
	});	
	server.on("/back-image.jpg", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/back-image.jpg", "image/jpeg");
	});
	server.on("/logo.png", HTTP_GET, [](AsyncWebServerRequest *request) {
		request->send(SPIFFS, "/logo.png", "image/png");
	});

	server.begin();
	delay(5000);

	logOutput("After server.begin()");
	for(int i = 1; i<=10;i++){
		logOutput((String)"Linia " + i);
	}
}

void loop() {
	logOutput("Beginning the loop()");
	delay(8000);
}
events.html

Code: Select all

<!DOCTYPE html>
<html>    
<head>
    <meta charset = "utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">    
    <link rel = "stylesheet" type = "text/css" href = "master.css">   
    <title>Events Log</title>
<script type="text/javascript" src="jquery-1.12.4.min.js"></script>
<script>
$(document).ready( function(){
$('#big-box').load('events_log.html');
refresh();
});
 
function refresh()
{
	setTimeout( function() {
	  $('#big-box').fadeOut('slow').load('events_log.html').fadeIn('slow');
	  refresh();
	}, 10000);
}
</script>
</head>


<body>
    <div id="big-box">
        <div class="textbox">%PLACEHOLDER_1%</div>
        <div class="textbox">%PLACEHOLDER_2%</div>
        <div class="textbox">%PLACEHOLDER_3%</div>
        <div class="textbox">%PLACEHOLDER_4%</div>
        <div class="textbox">%PLACEHOLDER_5%</div>
    </div>

</body>
</html>
events_log.html

Code: Select all

<!DOCTYPE html>
<html>
<div class="textbox">%PLACEHOLDER_1%</div>
<div class="textbox">%PLACEHOLDER_2%</div>
<div class="textbox">%PLACEHOLDER_3%</div>
<div class="textbox">%PLACEHOLDER_4%</div>
<div class="textbox">%PLACEHOLDER_5%</div>
</html>

HansDampf
Posts: 1
Joined: Sat Oct 23, 2021 1:07 pm

Re: [SOLVED] How should I use AJAX with ESP32 ?

Postby HansDampf » Sat Oct 23, 2021 1:16 pm

Hey,

I just saw your post here and I think your problem is similar to the one I have right now.

However, I am not too good in coding, but I would really like to solve my problem...

Can you help me, when I send my code to you?

Thanks a lot in advance :)

Who is online

Users browsing this forum: No registered users and 73 guests