Go Down

Topic: JSON WEB SERVER html (Read 7956 times) previous topic - next topic

pawqar

Hi everyone,

First of all, I want to apologize if this is not the correct place to post, and secondly as you notice my english it is not so good.

I hope you could help me. I want to show in a web page the values of my sensors. By now I am playing with a little example.

The system is composed by an arduino UNO and an Ethernet shield. Both work as a server. I made a "web page" in html:

("SERVER.txt"):
<!DOCTYPE html>
<html>
<head>
<script>
  function loadJson(fioNumber)  {
    var oJSON = new XMLHttpRequest();
    oJSON.open("GET","&fio" + fioNumber,true);
    oJSON.onreadystatechange = function()  {
      if (oJSON.readyState == 4)  {
        var json = eval("(" + oJSON.responseText + ")");
        document.getElementById("temperature").innerHTML = json.variables.temperature;
        document.getElementById("humidity").innerHTML    = json.variables.humidity;
        document.getElementById("address").innerHTML     = json.variables.address;
        document.getElementById("sleepCycle").innerHTML  = json.variables.sleepCycle;
        document.getElementById("asynchronus").innerHTML = json.variables.asynchronus;
        document.getElementById("name").innerHTML        = json.name;
      }
    };
    oJSON.send();
  }
</script>
</head>
<title>Servidor Web Arduino</title>
<body>

(F1.txt):

<FORM>
<p><INPUT TYPE=BUTTON OnClick="loadJson(1);" VALUE=FIO1></p>
<p>   name:        <div id="name"></div></p>
<p>   temperature: <div id="temperature"></div></p>
<p>   humidity:    <div id="humidity"></div></p>
<p>   address:     <div id="address"></div></p>
<p>   sleepCycle:  <div id="sleepCycle"></div></p>
<p>   asynchronus: <div id="asynchronus"></div></p>
</FORM>

</body>
</html>

I want to explain this, I create as files as sensors. If I have 4 sensors there are 4 files F1.txt,F2.txt,F3.txt,F4.txt. Itl would be sense with the sketch.

It is supposed that if a push the button, a http get request is sent to my board. And then it replies with a json object:
(this structure is saved as a file )
{
  "name": "fio1"
  "variables":{
     "address": "0x01",
          "temperature": "24",
          "humidity": "85",
          "asynchronus": "0",
          "sleepCycle": "20"
      }
}

And I think when it is send to the browser it will work... I show you my super-sketch:

// LIBRERIAS

#include <SPI.h>
#include <Ethernet.h>

#include <SD.h>  // ocupa 5KB 

char fio[3];
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x49, 0xFD };
byte ip[]  = { 192, 168, 1, 2 }; //aula de informática {172,31,55,44} // laboratorio { 192, 168, 112, 31 }
byte gateway[] = { 192, 168, 1, 1};
Server server(80); // Puerto 80, HTTP

// VARIABLES GLOBALES

//Ethernet Shield uses pins 10,11,12,13.
#define bufferMax 128
int bufferSize;
char buffer[bufferMax];

// SD
File myFile;

#define ssPin       10
#define chipSelect   4

void setup() {

  Ethernet.begin(mac, ip, gateway);
  server.begin();
  Serial.begin(9600);    // inicia comunicación serie
  pinMode(ssPin,OUTPUT);

  if (!SD.begin(chipSelect)) {  // inicia la tarjeta SD
    Serial.println("initialization failed!");
    return;
  }
}

void loop() {

  listenForClient();
}

void listenForClient() {

  Client client = server.available(); // espera a que haya datos disponilbles
  if ( client ) {
    waitForRequest(client); 
    int fioNumber = parseReceivedRequest(client);
    if (fioNumber != 0)
      sendGetResponse(fioNumber, client); 
  }
  client.stop();
}

void waitForRequest(Client client) {
  bufferSize = 0;
  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else
        if (bufferSize < bufferMax)
          buffer[bufferSize++] = c;
        else
          break;
    }
  }
  Serial.print(buffer);
}

int parseReceivedRequest(Client client) { // Petición recibida del tipo: "GET &fio1 HTTP/1.1"
  char* qm, * space;
  fio[0]=0;
   // strncpy does not automatically add terminating zero, but strncat does! So start with blank string and concatenate.
  if ( qm = strstr(buffer, "&fio") ) {  //apuntará a &
    qm     += 4; // sumando 5 apunta al valor deseado ( 4 letras --> "&", "f", "i", "o")
    space  = strstr(qm, " ") + 1;
    strncat(fio, qm, space-qm-5);
    return atoi(fio);
  } else if ( qm = strstr(buffer, " ") ) {
           webPrint(client);
           return 0;
         }  else
              return 0;
}


void sendGetResponse(int fioNumber, Client client) {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/plain");
  char filename[8];
  sprintf (filename, "F%d.jsn", fioNumber);
  filePrint(filename, client);
  client.println(" ");
}
 
void webPrint (Client client) { 
  filePrint("SERVER.TXT", client);
  char filename[6];
  int fiolength =  1, i = 1;
  for ( i = 1; i <= fiolength; i++ ) {
    sprintf (filename, "F%d.txt", i);
    filePrint (filename, client);
  }
  client.println("</body>");
  client.println("</html>");
}
// fuente: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1295739118
void filePrint (char filename[10], Client client){
  char a;
  if (myFile = SD.open(filename, FILE_READ)) { 
    while ( myFile.available() ) {
      a = (char)myFile.read();
      client.print(a);
      Serial.print(a);
    }
    myFile.close();                 // CERRAR FICHERO
  }
}

basically I wait for http request, I write http:\\192.168.1.2 in the browser... so I received "GET /HTTP1.1" as there is not information I print the web page. Then I wait  for clicking the button, so it will appear an GET fio1 /HTTP1.1. I parse this last one, and response to it. I search on the micro SD card for a file called fio1 and then print this information that is the json structure  and nothing happens. The goal was  when the structure arrives to the client the script execute itself and fill the gap I wrote as <div ahref ... .... but... Maybe I make a  mistake writing the html or the script or the http json response is not the correct one...

I am sorry it is sort of big... xD. Well, my questions are:

I do not have idea of html or http, just the few things I´ve read. And it is a mess. So I am not know if the html is well proposed. Or if I can response the http get request as I did just printing on the client, ...

I hope you could help me! Just read this is remarkable.

thank you !

undertakerbro

I'm no pro but, here's an idea that may simplify the matter. You want the arduino to become the server? I think that's kinda much for the little guy. Why not send the sensor readings to the PC and "processing" can send them to the webpage that is hosted by that PC. By send I mean write into a file and the Website will refresh the read on the file at a few secs interval. Hope this helps a little, if not sorry for me posting.

pawqar

Hi,

thanks for your answer. The next step it will be to use a server, as you said. But I was asked to do this more or less... Just show the information. There is other examples, like ajaxwebserver I found it here ->http://djgj.sub.jp/TETRASTYLE/arduino/Ajax_WebServer.txt

As you can see, the html it is not complicated. And json is supposed to do easier. But anyway thank you for your answer.

byes!


PeterH

As I understand it, you have a local web page that provides all the decorative stuff and just executes an HTTP request to the Arduino to retrieve some data. The page then processes the results and uses that to populate the page.

The basic approach seems OK. I haven't look at the detail of your JSON handling, but your JSON fragment is incorrect: the field names should not be quoted.

I suggest you get that sorted out by hard-coding your JSON string in the page and then use your existing logic to exec it into a variable; then you can print out whatever fields of that variable interest you.
I only provide help via the forum - please do not contact me for private consultancy.

zoomkat

Quote
I want to show in a web page the values of my sensors.


The below is a more conventional and possibly easier method to display values in a web page.

Code: [Select]

// arduino IDE 1.0
// for W5100 ethernet shield
// the IP address will be dependent on your local network/router
// port 80 is default for HTTP, but can be changed as needed
// use IP address like http://192.168.1.102:84 in your brouser
// or http://zoomkat.no-ip.com:84 with dynamic IP service
// use the \ slash to escape the " in the html
// meta refresh set for 2 seconds

#include <SPI.h>
#include <Ethernet.h>

int x=0; //set refresh counter to 0
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,102); // ip in lan
EthernetServer server(84); //server is using port 84

void setup()
{
  // start the server
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
     while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // see if HTTP request has ended with blank line
        if (c == '\n') {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
         
          //meta-refresh page every 2 seconds
          x=x+1;
          client.println("<HTML>");
          client.print("<HEAD>");
          client.print("<meta http-equiv=\"refresh\" content=\"2\">");
          client.print("<TITLE />Zoomkat's meta-refresh test</title>");
          client.print("</head>");
          client.println("<BODY>");
          client.print("Zoomkat's meta-refresh test IDE 1.0");
          client.println("<br />");
                   
          client.print("page refresh number ");
          client.println(x); //current refresh count
          client.println("<br />");
          client.println("<br />");
         
          client.print("Zoomkat's arduino analog input values:");
          client.println("<br />");
          client.println("<br />");
         
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(analogRead(analogChannel));
            client.println("<br />");
            }
           break;
          client.println("</BODY>");
          client.println("</HTML>");
         }
        }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

PeterH



The below is a more conventional and possibly easier method to display values in a web page.



Yeah, but that way the Arduino has to generate the whole page and whatever resources it needs to display.

The AJAX route originally proposed is a far more elegant solution. The Arduino only has to provide the data, and the rest of the page comes from somewhere else. It also means you can update the data without doing page turnarounds and just works better all round.
I only provide help via the forum - please do not contact me for private consultancy.

zoomkat

Quote
Yeah, but that way the Arduino has to generate the whole page and whatever resources it needs to display.


If you actually do some testing, my code can generate the bare minimum  data from the arduino that your project will need, probably less from what I see in the posted JSON stuff.

Quote
The AJAX route originally proposed is a far more elegant solution. The Arduino only has to provide the data, and the rest of the page comes from somewhere else. It also means you can update the data without doing page turnarounds and just works better all round.


More elegant? You can do pretty much what you describe with simple HTML. Doesn't AJAX require a folder on a server with supporting files the browser has to download for it to work? I made some web page sliders one time to control servos and I think it was an AJAX setup.
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

SurferTim

Quote
The AJAX route originally proposed is a far more elegant solution.

Very elegant! But how does it work for you?

Quote
I do not have idea of html or http, just the few things I´ve read.

May I suggest using an iFrame for the Arduino data. You can embed another document into a page. Here is some more reading:
http://www.w3schools.com/tags/tag_iframe.asp

zoomkat

Simple iframe html that keeps input to the web page in a box. To test, copy the code, paste in notepad, save on the desktop as test.htm. Bouble click the test.htm file (OK/yes the warnings about running the page from the desktop) to open it in your browser. You can then toggle between the two inputs to the iframe box without refreshing the main page.

Code: [Select]

<HTML>
<HEAD>
<TITLE>Zoomkat's arduino test</TITLE>
</HEAD>
Zoomkat's arduino frame test 9/13/11
<BR>
<BR>
Get data from arduino:
<BR>
|<a href="http://web.comporium.net/~shb/arduino.txt" target="DataBox" title="'arduino test'">Arduino</a>|
<a href="http://web.comporium.net/~shb/pix/slider1.jpg" target="DataBox"
title="'Show a pix'">PIX!</a>|
<BR>
<iframe src="http://web.comporium.net/~shb/arduino.txt" width="30%" height="200" name="DataBox">
</iframe>
<BR>
</HTML>

Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

PeterH


More elegant? You can do pretty much what you describe with simple HTML. Doesn't AJAX require a folder on a server with supporting files the browser has to download for it to work? I made some web page sliders one time to control servos and I think it was an AJAX setup.


Well, that depends if you want the web page to consist of a few lines of text in the default style, or to provide a visually attractive interactive user interface. By treating the Arduino as a source of data pulled into the page as required, and keeping the bulk of the page elsewhere, you are free to use all the ordinary web site authoring tools and techniques, style sheets, scripts, graphics and so on. If you want to host it locally, it would make sense to implement it as an HTML Application. But there's nothing to stop you hosting it on a web site somewhere else if you want it to be accessible remotely.
I only provide help via the forum - please do not contact me for private consultancy.

zoomkat

Quote
If you want to host it locally, it would make sense to implement it as an HTML Application.


How else would your arduino provide data for  your JSON/AJAX web page other than thru serving up the data via the http process? I've seen arduino code for telnet and udp but that would seem to be very complicated and unpractical in a web setup. One can make whiz-bang (and totally annoying) web pages using files/images stored on a big web server, but this really does not have anything to do with the arduino itself serving basic data to be displayed within the page.
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

PeterH


Quote
If you want to host it locally, it would make sense to implement it as an HTML Application.


How else would your arduino provide data for  your JSON/AJAX web page other than thru serving up the data via the http process? I've seen arduino code for telnet and udp but that would seem to be very complicated and unpractical in a web setup. One can make whiz-bang (and totally annoying) web pages using files/images stored on a big web server, but this really does not have anything to do with the arduino itself serving basic data to be displayed within the page.


I think we're talking at cross purposes.

In your example, the Arduino publishes some HTML which is displayed in the browser. This means that either what is displayed is formatted very crudely, or your Arduino has to serve out a rich HTML page and whatever resources it needs to render properly. The Arduino isn't a good platform for serving out rich HTML documents, style sheets, scripts and all that. All you really want from the Arduino is the data itself, whether encoded in XML, JSON, CSV or whatever. For an AJAX application, JSON is a perfectly sensible way to encode the data.

Implementing this as an AJAX application that gets data from the Arduino simply gives you a better solution than serving your whole page from the Arduino.
I only provide help via the forum - please do not contact me for private consultancy.

zoomkat

Quote
Implementing this as an AJAX application that gets data from the Arduino simply gives you a better solution than serving your whole page from the Arduino.


I never said anything about serving a "whole page" from the arduino, just the desired data. Below is link for getting the minimum no frills basic data from the arduino. The AJAX, html, or other methods of the display page construction would be up to the page developer and what they think will best suite the end viewer.

http://arduino.cc/en/Tutorial/WebServer
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

PaulS

Quote
The Arduino isn't a good platform for serving out rich HTML documents, style sheets, scripts and all that.

It's perfectly capable of referring to style sheets, scripts, etc. that are stored elsewhere, and letting the browser fetch all the right files.

pawqar


As I understand it, you have a local web page that provides all the decorative stuff and just executes an HTTP request to the Arduino to retrieve some data. The page then processes the results and uses that to populate the page.

The basic approach seems OK. I haven't look at the detail of your JSON handling, but your JSON fragment is incorrect: the field names should not be quoted.

I suggest you get that sorted out by hard-coding your JSON string in the page and then use your existing logic to exec it into a variable; then you can print out whatever fields of that variable interest you.


Hi Peter,

thank you for your answer. You understood it quite well. I correted the json file, thanks. And I did as you said, separately, I write html web server. And It worked, but...
<!DOCTYPE html>
<html>
<head>
<script>
  function loadJson(fioNumber)  {
        var json = {
  name: "fio1",
  variables: {
     address: "0x01",
     temperature: "24",
     humidity: "85",
          asynchronus: "0",
          sleepCycle: "20"
      }}
;
alert(json);
        document.getElementById("temperature").innerHTML = json.variables.temperature;
        document.getElementById("humidity").innerHTML    = json.variables.humidity;
        document.getElementById("address").innerHTML     = json.variables.address;
        document.getElementById("sleepCycle").innerHTML  = json.variables.sleepCycle;
        document.getElementById("asynchronus").innerHTML = json.variables.asynchronus;
        document.getElementById("name").innerHTML        = json.name;
      };
</script>
</head>
<title>Servidor Web Arduino</title>
<body>

<FORM>
<p><INPUT TYPE=BUTTON OnClick="loadJson(1);" VALUE=FIO1></p>
<ul>
<li>name:         <a id="name"></a> </li>
<li> temperature: <a id="temperature"></a></li>
<li>humidity:     <a id="humidity"></a></li>
<li>address:      <a id="address"></a></li>
<li>sleepCycle:   <a id="sleepCycle"></a></li>
<li>asynchronus:  <a id="asynchronus"></a></li>
</FORM>

</body>
</html>

but...when I post on the card ... well... on browser, I open the console that show the code ... (in chrome F12) and it said that it couldn´t find temperature (which is part of variables...) well I simplified the structure... { name = "fio1, temperature="34"... etc} ... but Is it json? xD Anyway,  if I enter the IP address of my arduino it shows

fio1 (as a button)

name: undefined
temperature: undefined
humidity: undefined
address: undefined
sleepCycle: undefined
asynchronus: undefined

undefined¿? I searched through the web but... I am lost.
Could it be that the it is not response?
Did I send a bad response?

void sendGetResponse(int fioNumber, Client client) {
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/plain");
  client.println("Connection: close");
  client.println(" ");
  char filename[8];
  sprintf (filename, "F%d.jsn", fioNumber);
  filePrint(filename, client);
  client.flush(); 
}

I directly write the jsonfile  (client.print ...)

Thank you for your time, I really appreciate it.

greetings!

Go Up