ESP8266WebServer and json

Hi, I have setup a webpage with ajax to connect to a db and return a json with some data.
I need now to retrieve the json data but I'm not clear on how to do it with the ESP8266WebServer library and with the server.on() method.
I checked the documentation but couldn't find example with json file.
this is the full code so if you load it on your nodemcu it will work

#define DEBUG

#ifdef DEBUG
  #define SB(...) Serial.begin(__VA_ARGS__)
  #define SP(...) Serial.print(__VA_ARGS__)
  #define SPL(...) Serial.println(__VA_ARGS__)
#else
  #define SB(...) 
  #define SP(...)
  #define SPL(...)
#endif

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
 
const char* ssid = "";
const char* password = "";
 
ESP8266WebServer server(80);   //instantiate server at port 80 (http port)

IPAddress ip(192, 168, 1, 7); // where xx is the desired IP Address
IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
IPAddress subnet(255, 255, 255, 0); // set subnet mask to match your network

String page = "";

void setup(void){
  
page="<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset='utf-8'/>"
"<meta name='viewport' content='width=device-width, initial-scale=1'>"
"<meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />"
"<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css' integrity='sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B' crossorigin='anonymous'>"
"<link rel='stylesheet' type='text/css' href='http://www.francescosoave.com/blind/style.css'>"
"<script src='https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js' type='text/javascript'></script>"
"<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>"
"</head>"
"<body>"
"<div class='container'>"
"<div class='row'>"
"<table class='table' id='radioForm'>"
"<thead>"
"<tr><th>Blind</th></tr>"
"</thead>"
"<tbody>"
"<tr><td align='center'>"
"<input id='1' type='radio' name='radioBtn' value='1' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='2' type='radio' name='radioBtn' value='2' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='3' type='radio' name='radioBtn' value='3' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='4' type='radio' name='radioBtn' value='4' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='5' type='radio' name='radioBtn' value='5' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='6' type='radio' name='radioBtn' value='6' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='7' type='radio' name='radioBtn' value='7' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='timer' name='timerBtn' type='button'>"
"
"
"<p>Timer is <span id='timerMsg'></span></p>"
"</td></tr>"
"</tbody>"
"</table>"
"</div>"
"</div>"
"<script>"
"$( document ).ready(function() {"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBread.php',"
"data: {'pw':'Blind4r'},  "
"success: function(jsonObj) {"
"$('#' + jsonObj[0].cur_pos).prop('checked', true);"
"if(jsonObj[0].timer == 0){"
"$('#timer').attr({"
"'class': 'btn btn-success',"
"value: 'TURN ON'"
"});"
"$('#timerMsg').html('off');"
"}else{"
"$('#timer').attr({"
"'class': 'btn btn-danger',"
"value: 'TURN OFF'"
"});"
"$('#timerMsg').html('on');"
"}"
"},"
"error: function(jsonObj){"
"}"
"});"
"setInterval(function(){"
"$('#timerMsg').fadeOut(function () {"
"$(this).fadeIn();"
"});"
"} ,1000);"
"});"
"$('#timer').on('click', function() {"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBtimer.php',"
"data: {'pw':'Blind4r'},"
"success: function(jsonObj) { "
"if(jsonObj[0].timer == 1){"
"$('#timer').attr({"
"'class': 'btn btn-danger',"
"value: 'TURN OFF'"
"});"
"$('#timerMsg').html('on');"
"}else{"
"$('#timer').attr({"
"'class': 'btn btn-success',"
"value: 'TURN ON'"
"});"
"$('#timerMsg').html('off');"
"}"
"},"
"error: function(jsonObj){"
"}"
"});"
"});"
"$('#radioForm input').on('change', function() {"
"var timer_val = $('input[name=radioBtn]:checked', '#radioForm').val();"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBradio.php',  "
"data: {'pw':'Blind4r', 'radio':timer_val},  "
"success: function(jsonObj) { "
"},"
"error: function(jsonObj){"
"}"
"});"
"});"
"</script>"
"</body>"
"</html>";

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  WiFi.config(ip, gateway, subnet); 
  delay(1000);
  SB(115200);
  WiFi.begin(ssid, password); //begin WiFi connection
  delay(1000);
  SPL();
 
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    SP("waiting for connection.");
    digitalWrite(LED_BUILTIN, LOW);
  }
  SPL();
  SP("Connected to ");
  SPL(ssid);
  SP("IP address: ");
  SPL(WiFi.localIP());
   
  server.on("/", [](){
    server.send(200, "text/html", page);
  });
//  server.on("/LEDOn", [](){
//    server.send(200, "text/html", page);
//    digitalWrite(LED_BUILTIN, HIGH);
//    delay(1000);
//  });
//  server.on("/LEDOff", [](){
//    server.send(200, "text/html", page);
//    digitalWrite(LED_BUILTIN, LOW);
//    delay(1000); 
//  });
  server.begin();
  SPL("Web server started!");
}
 
void loop(void){
  server.handleClient();
}

The ajax is successfully returning the json (tested in browser) I just don't get how to access it from here.

Thanks!
L.

the ESP8266WebServer handles the POST request only as x-www-form-urlencoded, multipart or file upload. your option is upload handler. See the WebUbdate example. Or if the json string is short send it as x-www-form-urlencoded as json={...}. Or do not use WebServer library and write your own simple HTTP server with WiFiServer

Hi, thanks. Ok, I'll go with the last solution..however could you please link me to which library/example I should look at? Asking because I have a few different and I'm getting confused. Thanks!

I can't check now the ESP8266 library examples, byr other WiFi libraries have a basic WebServer example with WiFiServer.

ok but I'll need both WifiServer to host the page and WifiClient to read the incoming bytes right?

WiFiClient is s a tcp socket. WiFiServet is a tcp servet socket. servet socket listens on a port and if someone connects, creates a socket to communicate with that calling socket.

sorry I don't follow you..but I should need something like this example right? https://www.arduino.cc/en/Tutorial/WiFiWebServer and there are both client and server

Hi there, here's an update. I got rid of the ESP8266Webserver library and now I'm using only the ESP8266WiFi. So far I've managed to correctly display the webpage. However I'm not able to get the json that is sent as response from the ajax requests.
I need some guidance please.

Thanks!!

This is what gets printed to the Serial Monitor when I open it

Connected to TALKTALK-17409C
IP address: 192.168.1.7
Web server started!
new client
GET / HTTP/1.1

Host: 192.168.1.7

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3

Accept-Encoding: gzip, deflate

DNT: 1

Connection: keep-alive

Upgrade-Insecure-Requests: 1

Cache-Control: max-age=0




Client disonnected

Here's the full code (just change ssid and pw and it will work).

#define DEBUG

#ifdef DEBUG
  #define SB(...) Serial.begin(__VA_ARGS__)
  #define SP(...) Serial.print(__VA_ARGS__)
  #define SPL(...) Serial.println(__VA_ARGS__)
#else
  #define SB(...) 
  #define SP(...)
  #define SPL(...)
#endif

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
 
const char* ssid = "TALKTALK-17409C";
const char* password = "HPHRKJYX";
 
WiFiServer server(80);   //instantiate server at port 80 (http port)

IPAddress ip(192, 168, 1, 7); // where xx is the desired IP Address
IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
IPAddress subnet(255, 255, 255, 0); // set subnet mask to match your network

String page = "";

void setup(void){
  
page="<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset='utf-8'/>"
"<meta name='viewport' content='width=device-width, initial-scale=1'>"
"<meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />"
"<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css' integrity='sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B' crossorigin='anonymous'>"
"<link rel='stylesheet' type='text/css' href='http://www.francescosoave.com/blind/style.css'>"
"<script src='https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js' type='text/javascript'></script>"
"<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>"
"</head>"
"<body>"
"<div class='container'>"
"<div class='row'>"
"<table class='table' id='radioForm'>"
"<thead>"
"<tr><th>Fran's Blind</th></tr>"
"</thead>"
"<tbody>"
"<tr><td align='center'>"
"<input id='1' type='radio' name='radioBtn' value='1' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='2' type='radio' name='radioBtn' value='2' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='3' type='radio' name='radioBtn' value='3' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='4' type='radio' name='radioBtn' value='4' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='5' type='radio' name='radioBtn' value='5' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='6' type='radio' name='radioBtn' value='6' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='7' type='radio' name='radioBtn' value='7' />"
"</td></tr>"
"<tr><td align='center'>"
"<input id='timer' name='timerBtn' type='button'>"
"
"
"<p>Timer is <span id='timerMsg'></span></p>"
"</td></tr>"
"</tbody>"
"</table>"
"</div>"
"</div>"
"<script>"
"$( document ).ready(function() {"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBread.php',"
"data: {'pw':'Blind4r'},  "
"success: function(jsonObj) {"
"$('#' + jsonObj[0].cur_pos).prop('checked', true);"
"if(jsonObj[0].timer == 0){"
"$('#timer').attr({"
"'class': 'btn btn-success',"
"value: 'TURN ON'"
"});"
"$('#timerMsg').html('off');"
"}else{"
"$('#timer').attr({"
"'class': 'btn btn-danger',"
"value: 'TURN OFF'"
"});"
"$('#timerMsg').html('on');"
"}"
"},"
"error: function(jsonObj){"
"}"
"});"
"setInterval(function(){"
"$('#timerMsg').fadeOut(function () {"
"$(this).fadeIn();"
"});"
"} ,1000);"
"});"
"$('#timer').on('click', function() {"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBtimer.php',"
"data: {'pw':'Blind4r'},"
"success: function(jsonObj) { "
"if(jsonObj[0].timer == 1){"
"$('#timer').attr({"
"'class': 'btn btn-danger',"
"value: 'TURN OFF'"
"});"
"$('#timerMsg').html('on');"
"}else{"
"$('#timer').attr({"
"'class': 'btn btn-success',"
"value: 'TURN ON'"
"});"
"$('#timerMsg').html('off');"
"}"
"},"
"error: function(jsonObj){"
"}"
"});"
"});"
"$('#radioForm input').on('change', function() {"
"var timer_val = $('input[name=radioBtn]:checked', '#radioForm').val();"
"$.ajax({"
"type: 'GET',"
"dataType: 'jsonp', "
"url: 'http://www.francescosoave.com/blind/DBradio.php',  "
"data: {'pw':'Blind4r', 'radio':timer_val},  "
"success: function(jsonObj) { "
"},"
"error: function(jsonObj){"
"}"
"});"
"});"
"</script>"
"</body>"
"</html>";

  WiFi.config(ip, gateway, subnet); 
  delay(1000);
  SB(115200);
  WiFi.begin(ssid, password);
  delay(1000);
  SPL();
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    SP("waiting for connection.");
  }
  
  SPL();
  SP("Connected to ");
  SPL(ssid);
  SP("IP address: ");
  SPL(WiFi.localIP());

  server.begin();
  SPL("Web server started!");
}


void loop(void){

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  SPL("new client");
  while(!client.available()){
    delay(1);
  }
  
  while(client.available()){
  String  req = client.readStringUntil('\r');
    SPL(req);
  }
  
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
  s += page;
  s += "\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  SPL("Client disonnected");
}

first copy the complete http client's request to Serial to see how it looks.

Hey thanks! I thought I was doing it already with this bit?

while(client.available()){
  String  req = client.readStringUntil('\r');
    SPL(req);
  }

which returns this

GET / HTTP/1.1

Host: 192.168.1.7

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3

Accept-Encoding: gzip, deflate

DNT: 1

Connection: keep-alive

Upgrade-Insecure-Requests: 1

Cache-Control: max-age=0

the empty lines are because every next line starts with \n from the end of the previous line.

you do not print the body of the request because it doesn't end with \r.

the printout is not a complete http request because if there is a small gap in receive the while loop ends

copy all bytes to Serial with

  byte b;
  while (client.readBytes(&b, 1) > 0) {
    Serial.write(b);
  }

readBytes waits for the next byte

I see. However I'm still getting the same back with the new code

GET / HTTP/1.1
Host: 192.168.1.7
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

it is a GET request it can't have body with json. how do you send it?

Juraj:
it is a GET request it can't have body with json. how do you send it?

sorry not sure of what you are asking..the code running on the nodemcu is above, the html page with the ajax is in the page variable that I'm printing out at the bottom of the loop().
This connects to some PHP pages hosted somewhere else and which are returning a json for each request.

up

make the previous post complete