Go Down

Topic: Using HTML GET (Arduino is the AP...) (Read 10154 times) previous topic - next topic

tgr8db

Aug 29, 2016, 12:01 pm Last Edit: Aug 29, 2016, 07:44 pm by tgr8db
Respected community ,

I have set up my Arduino as a web server (WiFi - esp8266) . Then I made a html web page (on the Arduino itself using server.send() function ..  ) which has two text box for two variables x and y . Now , I want to take the values of x and y (float) and use them in my sketch . I know that this should be simple but I am unable to understand the various example sketches provided , can you people please help me out ?

Code: [Select]

<html><body>
<form  name='frm' id='frm' method='get'>
<input type='text' name='num'   >
<input type='text' name='name'  >
<input type='submit' value='Submit'>   </form>

   
</body></html>

PaulS

Quote
can you people please help me out ?
Sure. Get rid of the java scripting crap. Use JUST standard HTML form items, including items of type SUBMIT.

Have two text boxes and a submit button on the same form. When you do, and you have an appropriate method, the GET request that is generated will NOT be the same when the form is first requested and when the submit button is pressed.

Actually paying attention to the complete GET request will be necessary.

PieterP

Also, why not let the ESP8266 do all the server work? Just send x and y from the ESP to the Arduino.
This way, you can focus on the actual Arduino code, not having to worry about what the webpage is doing, and just use the values received on the serial port.

tgr8db

#3
Aug 29, 2016, 07:28 pm Last Edit: Aug 29, 2016, 07:45 pm by tgr8db Reason: Adding more information...
When we 'submit' the values of the variable using GET method in HTML , How do we take that value and use it in the sketch ? This was my question . sorry for not being clear enough... (AND I edited the HTML code as suggested...)

PaulS

Quote
When we 'submit' the values of the variable using GET method in HTML , How do we take that value and use it in the sketch ?
Have you looked at the complete GET request, as received by the Arduino, when the page is first requested, and when the submit button(s) are pressed? They will be different. The first time, the GET request should look something like "GET / HTTP/1.1". The second should look something like "GET /?num=12&name=Joe HTTP/1.1".

It is not terribly difficult to detect the presence of the ? in the request, and to extract the tokens after it ("num", "12", "name", and "Joe") and to copy the appropriate tokens to the right variables, with any required conversion.

PieterP

#5
Aug 29, 2016, 07:42 pm Last Edit: Aug 29, 2016, 07:47 pm by PieterP
It is not terribly difficult to detect the presence of the ? in the request, and to extract the tokens after it ("num", "12", "name", and "Joe") and to copy the appropriate tokens to the right variables, with any required conversion.
No need to, you can use the hasArg() and arg() methods of the WebServer class:
Code: [Select]
if(!server.hasArg("argument_name")) {
  server.send(500, "text/plain", "Wrong arguments");
  return;
}
int argument_value_int = server.arg("argument_name");
// or
String argument_value_str = server.arg("argument_name");


Edit: I tried it on the ESP8266 itself, using the ESP8266WebServer class, I'm not entirely sure whether or not it works on an Arduino, but I suspect it will, and even if doesn't, there should be a more elegant solution than doing it 'by hand', right? Well, not that it's difficult, just use strstr or strtok on the GET request.

tgr8db

#6
Aug 29, 2016, 08:03 pm Last Edit: Aug 29, 2016, 08:18 pm by tgr8db
I am unable to understand GET method at all . Is it possible to provide the Sketch for the following web form ? (Like just store the whole URL in a string..)

Code: [Select]


<html><body>
<form  name='frm'  method='get'>
<input type='text' name='x'   >
<input type='submit' value='Submit'>   </form>

  
</body></html>



And the basic sketch is :

Code: [Select]


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>

/* Set these to your desired credentials. */
const char *ssid = "thenetwork";
const char *password = "password";

ESP8266WebServer server(80);
WiFiClient client;

/* Go to http://192.168.4.1 in a web browser
 * connected to this access point to see it.
 */

void webpage() {
  server.send(300, "text/html", "<html><body><form  name='frm'  method='get'><input type='text' name='x'   ><input type='submit' value='Submit'>   </form></body></html>");
}


void setup() {
  Serial.begin(9600);
  Serial.println();
  Serial.println("Configuring access point...");
  Serial.println();
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.println("AP IP address: ");
  Serial.println(myIP);
  server.on("/", webpage());
  server.begin();
  Serial.println();
  Serial.println("HTTP server started");
  
}

void loop() {
  server.handleClient();
  String url=""; // I want this string to store the url .. ie "/x=" part...
}


PaulS

Code: [Select]
  String url=""; // I want this string to store the url .. ie "/x=" part...
But, you have abdicated all responsibility for dealing with what the client wants:

Code: [Select]
  server.handleClient();
You can't have it both ways. Either you deal with what the client wants or you make handleClient() do what you want, possibly returning a pointer to char that points to the collected URL.

PieterP

I think this is what you wanted?
Code: [Select]

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>

/* Set these to your desired credentials. */
const char *ssid = "ESP8266";
const char *password = "thereisnospoon";

char    inString[32]      ;         // string for incoming serial data
int     stringPos = 0     ;         // string index counter                // what do you use this for?
boolean startRead = false ;         // is reading?

ESP8266WebServer server(80);
WiFiClient client;
/* Go to http://192.168.4.1 in a web browser
 * connected to this access point to see it.
 */

void webpage() {
  server.send(200, "text/html", "<html><body><form  name='frm'  method='post'><input type='text' name='x'   ><input type='submit' value='Submit'>   </form></body></html>");
}
void response(){
  if(server.hasArg("x") && (server.arg("x").length()>0)){ // TODO check that it's not longer than 31 characters
    Serial.print("User entered:\t");
    Serial.println(server.arg("x"));
    inString = server.arg("x");
    server.send(200, "text/html", "<html><body><h1>Successful</h1><a href='/'>Home</a></body></html>");
  } else {
    server.send(400, "text/html", "<html><body><h1>HTTP Error 400</h1><p>Bad request. Please enter a value.</p></body></html>");
  }
}

void setup() {
  Serial.begin(9600);
  Serial.println();
  Serial.println("Configuring access point...");
  Serial.println();
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.println("AP IP address: ");
  Serial.println(myIP);
  server.on("/",HTTP_GET, webpage);
  server.on("/",HTTP_POST,response);
  server.begin();
  Serial.println();
  Serial.println("HTTP server started");
 
}

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


I changed the method to POST, so that you can differentiate between the request of the form page, and the submitting of the form.

tgr8db

I think that I will have to explain my whole story now. (The reason I want GET) . I have a school project in which I am making a Phone controlled WiFi Car . Basically I ripped off the Main board and made the necessary connections (switch) as explained by http://www.gammon.com.au/switches . Then I created a 'game' (for Android/iOS) in Unreal Engine 4 which basically edits the URL (and loads it in background) when the input values from the gamepad are given.

I want to take the values (float , can be negative) fb (forward/backward) and lr (left/right) from that URL and use it to do any stuff that I want with it by storing the values in a same named variable in the Arduino sketch .

Let's consider a made-up Arduino URL "http://192.168.4.1/?fw=10.3&lr=2.8" . Now , I want you guys to help me take the part after '/' and store it in a String . I am a total NOOB in this field , so it would be really helpful if you could explain it too (just  a bit).

Thanks in advance... 

PieterP

#10
Aug 29, 2016, 09:58 pm Last Edit: Aug 29, 2016, 10:04 pm by PieterP
(The reason I want GET)
Why? POST is the way to go when sending data over to the server?
If you want low latency, I'd suggest you use WebSockets. (It keeps the connection open, with GET or POST, you need to establish a new connection everytime you send a message, which is slow).
From what I read online, it is perfectly possible to use WebSockets with Unreal Engine 4. Receiving WebSockets, and running a WebSocket server on the ESP8266 is quite easy as well, using this library.

With that out of the way, I'll try to explain how it works:
Code: [Select]
ESP8266WebServer server(80);
This line creates a web server on port 80. This means that your browser can connect on this port and send HTTP requests, to get a webpage, for example.

Code: [Select]
server.on("/",HTTP_GET, webpage);
server.begin();

Here we add a handler for "/", meaning that if the server gets a GET request for the address "/" (root), the function 'webpage' is executed.
After that, we start the server, so it can start taking requests.

Code: [Select]
void webpage() {
  server.send(200, "text/html", "<html><body><form  name='frm'  method='post'><input type='text' name='x'   ><input type='submit' value='Submit'>   </form></body></html>");
}

This is that handler function that is executed when GET "/" is requested.
The server sends a HTTP 200 status code, meaning that everything is ok, it understood the request, and knows what to send back. Then we say that we are going to send HTML (HyperText Markup Language, the language webpages are written in), and finally, we send the actual HTML.
The browser will then receive this response, and display the webpage.

The browser can also add parameters (arguments) to the URL, e.g. "/?fw=10.3&lr=2.8"
To get the value for these parameters, we can use
Code: [Select]
char * fw = server.arg("fw");
But first we want to check whether or not the browser added these parameters, we can check that using
Code: [Select]
if(server.hasArg("fw")){
  String fw = server.arg("fw");
}


Finally, we can convert this string of characters to a floating point number, using the 'toFloat()' function
Code: [Select]
if(server.hasArg("fw")){
  String  fw = server.arg("fw");
  float forward = fw.toFloat();
}
if(server.hasArg("lr")){
  String  lr = server.arg("lr");
  float left_right= lr.toFloat();
}

Then you can use that value to drive your motors.

I only mentioned the browser as a client, but this can be pretty much any modern application.

PaulS

Quote
Finally, we can convert this string of characters to a floating point number, using the 'toFloat()' function
Storing the result in a local variable (local to the block) is pointless.

PieterP

Storing the result in a local variable (local to the block) is pointless.
Agreed, but it was just for demonstrational purposes, (to show it's of data type float, and how to convert it). He could do whatever he wants with that value, probably store it in a global variable and handle it in the loop, or call a function that controls motor speed directly from the webpage handler function.

tgr8db

Thanks for the help ,

NOW , I am really unable to understand web sockets at all. I get the way that they work but I don't understand their implementation . As I have already said I am a noob in networking and Arduino . So , what I would like you to help me with is :
     
  • Set up a sketch which completely hosts the webpage (acts as the server) and receives x from the client and stores it in a local variable (OR displays it in the serial monitor).
  • Make a webpage which sends the value of x through a socket connection (using a basic submit button).


I have really tried searching up this stuff but it just doesn't click in my head.

PieterP

#14
Aug 30, 2016, 05:36 pm Last Edit: Aug 30, 2016, 05:37 pm by PieterP
Set up a sketch which completely hosts the webpage (acts as the server) and receives x from the client and stores it in a local variable (OR displays it in the serial monitor).
If I'm not mistaken, this site is called "Arduino Forum", and not "Arduino Free Code Distribution Service" ;)

Show us what you've tried already, so we can work on that.
Did you download the WebSocket library I suggested?
Take a look at the examples, there is one that controls the brightness of 3 LEDs from a webpage.
Doesn't that sound exactly like what you are trying to do? (If you use motors instead of LEDs, of course.)

Check out the example, try to understand how it works, look it up on Google if there's something you don't understand. If that's not enough, you can ask it in this thread, and we can take a look at it together.

If you look at the example, try to find out how they start the connection (also, what libraries are they using?), what happens if data is received (what function handles the receiving of messages, how are the messages converted to the right type), next, find out how the webpage sends data to the ESP (the HTML and JavaScript for the webpage are on line 103, as one long string, not very handy to find out what's going on, so save it as a separate .html file and open it in Chrome. Now you can press CTRL+U to view the source of the page.)
Finally, try to figure out how the ESP8266 can send data back to the browser, and how the webpage receives it.

If you have a general idea of how it works, you can try to upload it to the ESP, and open the real webpage in the browser.

The last step is to use the information you got to write your own sketch, or adapt the example in such a way that you can use it for your project.

Good luck!
Pieter

Go Up