Home / Codes / How to Send HTTP Post and Get Requests Using Arduino ENC28J60 Ethernet Shield

How to Send HTTP Post and Get Requests Using Arduino ENC28J60 Ethernet Shield

Image result for enc28j60 ethernet shield

In this IoT age, there are several ways of sending and getting data to/from a microcontroller to a remote server. This article will be the first part of a series about such ways through the Arduino ENC28J60 shield or module. Here I will be showing the classic way of communicating via the Internet: HTTP requests.

Introduction

An HTTP request is how most web browsers request a web page from a server. For example, when you visit this website, your browser will send this request:

GET / HTTP/1.1
Host: circuitxcode.com

The server handling this website hears the request and then returns a response and all the code for viewing the website on the browser (HTML, CSS, JS, etc.).

A microcontroller with Internet capabilities can also do such requests. In this tutorial, I will feature the Arduino ENC28J60 shield or module. However, the codes here might also be usable for other shields like W5100, etc. 

Sending a GET Request

A GET request gets data from a remote server. When done using a web browser, GET requests can be cached, bookmarked or saved in the browser’s history. As such, GET requests are less secure compared to POST request. 

The code below uses GET to acquire the homepage of this website:

#include <UIPEthernet.h>

EthernetClient client;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

void setup() {
  Serial.begin(9600);
  char server[] = "www.circuitxcode.com";
  if(Ethernet.begin(mac) == 0){
    Serial.println("Failed to configure Ethernet using DHCP");
    while(1); //do nothing if ethernet failed to start
  }
  if (client.connect(server,80)){
      Serial.println("Connected to server");
      client.println("GET / HTTP/1.1");
      client.println("Host: circuitxcode.com");
      client.println();
  }else{
      Serial.println("Connection to server failed");
  }
}

void loop() {  
  while(client.connected()){
    if(client.available()){
      char c = client.read();
      Serial.print(c);  
    }
  }
}

If you run this code on an Arduino, the serial monitor will show this:

Arduino response to HTTP GET request
This is an example of a response from a server. There is no HTML page on the response because this site is routed through a different server but that’s too complicated for this post. Let’s just run through the code for now.

The first lines contain this:

#include <UIPEthernet.h>

EthernetClient client;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

Here the UIPEthernet library is included as the built-in Ethernet library doesn’t support the EN28J60 shield/module. 

We then initialize the EthernetClient object and then create a MAC address. The MAC address could be anything as long as it isn’t the same as any other devices on your LAN. Some ethernet shields have their MAC address printed on the board so you may use that.

Here’s the setup() function:

void setup() {
  Serial.begin(9600);

  char server[] = "www.circuitxcode.com";
  if(Ethernet.begin(mac) == 0){
    Serial.println("Failed to configure Ethernet using DHCP");
    while(1); //do nothing if ethernet failed to start
  }

  if (client.connect(server,80)){
      Serial.println("Connected to server");
      client.println("GET / HTTP/1.1");
      client.println("Host: circuitxcode.com");
      client.println();
  }else{
      Serial.println("Connection to server failed");
  }
}

I created a server char array where the server name is assigned to. Then, we check if the ethernet device is able to initiate connection through DHCP. If this initialization is unsuccessful, there’s no point in continuing so the program ends with an infinite loop.

If the DHCP initialization is successful, we connect to the server using 

client.connect(server,80)

This function returns true if successful and false if not. The second parameter in the function is the port number. Port 80 is the port for HTTP request while 443 is for HTTPS. We will be using more port numbers as we go along with this series.

If we are able to connect to the server, we now send the request:

client.println("GET / HTTP/1.1");
client.println("Host: circuitxcode.com");
client.println();

Note the extra client.println() is necessary.

The simplest GET request follows this format:

GET <page> HTTP/1.1
Host: <website URL>

In the Arduino sketch, we are requesting for the home page so there’s only a “/”. If we want to request another page, like contact.php for example, then this is the request:

GET /contact.php HTTP/1.1
Host: <website URL>

Browsers typically send more headers than what I used here.

The loop() function waits for any response from the server and prints it to the serial monitor.

void loop() {  
  while(client.connected()){
    if(client.available()){
      char c = client.read();
      Serial.print(c);  
    }
  }
}

The GET request, again, is for receiving data from the server. If we want to send data, we use POST request.

Sending a POST Request

Unlike the GET request, a POST request will not be cached, bookmarked or remain in the browser’s history. This makes POST requests more secure than GET requests. Moreover, you can use POST requests to send data to the server.

Here’s an Arduino sketch for sending a POST request:

#include <UIPEthernet.h>

EthernetClient client;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

void setup() {
  Serial.begin(9600);

  char server[] = "www.circuitxcode.com";

  String data = "sensor1=";
  data += analogRead(A0);
  data += "sensor2=";
  data += analogRead(A1);

  if(Ethernet.begin(mac) == 0){
    Serial.println("Failed to configure Ethernet using DHCP");
    while(1);
  }

  if (client.connect(server,80)){
      Serial.println("Connected to server");
      client.println("POST / HTTP/1.1");
      client.println("Host: circuitxcode.com");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(data.length());
      client.println();
      client.println(data);
      client.println();
  }else{
      Serial.println("Connection to server failed");
  }
}

void loop() {  
  while(client.connected()){
    if(client.available()){
      char c = client.read();
      Serial.print(c);  
    }
  }
}

The first difference in this sketch with the first one is we need to define the data we will be sending:

String data = "sensor1=";
data += analogRead(A0);
data += "&sensor2=";
data += analogRead(A1);

Here, I created a string and embedded the readings from analog ports A0 and A1. This is assuming I have some sensor connected in these ports. The data string would look like this:

sensor1=100&sensor2=200

The second difference is this part:

if(client.connect(server,80)){
      Serial.println("Connected to server");
      client.println("POST / HTTP/1.1");
      client.println("Host: circuitxcode.com");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(data.length());
      client.println();
      client.println(data);
      client.println();
}

Besides changing GET to POST, notice that I added these:

client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(data.length());
client.println();
client.println(data);
client.println();

The first line tells the server what type of data we are sending. The next lines tell the length of the data to be sent (which is the data string). Then the last part of the request is the data string itself.

The format for a simple POST request is like this:

POST <page> HTTP/1.1
Host: <website URL>
Content-Type: <content-type>
Content-Length: <length of data>

<data>

When you upload the sketch, expect the same reply as the previous sketch. 

Typically, POST request will not provide the HTML code of the page unless the page you are requesting is explically sending the HTML code. 

So what happens to the data we just sent? If the page to where it was sent is using PHP, two variables will now have been created: $_POST[‘sensor1’] and $_POST[‘sensor2’]. Now it is up to the web developer what he will do with the contents of these variables.

Example With PHP Code

For example, let’s create a sensor.php file:

<html>
<body>
<?php
if(isset($_POST[‘sensor1’] && $_POST[‘sensor2’])){
  echo ‘<h1>Sensor 1=’.$_POST[‘sensor1’].’</h1>’;
  echo ‘<h1>Sensor 2=’.$_POST[‘sensor2’].’</h1>’;
}
?>
</body>
</html>

Let me place this php file on the root directory of this website. The Arduino sketch for sending a POST request becomes this:

#include <UIPEthernet.h>

EthernetClient client;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

void setup() {
  Serial.begin(9600);

  char server[] = "www.circuitxcode.com";

  String data = "sensor1=";
  data += analogRead(A0);
  data += "sensor2=";
  data += analogRead(A1);
  if(Ethernet.begin(mac) == 0){
    Serial.println("Failed to configure Ethernet using DHCP");
    while(1);
  }

  if (client.connect(server,80)){
      Serial.println("Connected to server");
      client.println("POST /sensor.php HTTP/1.1");
      client.println("Host: circuitxcode.com");
      client.println("Content-Type: application/x-www-form-urlencoded");
      client.print("Content-Length: ");
      client.println(data.length());
      client.println();
      client.println(data);
      client.println();
  }else{
      Serial.println("Connection to server failed");
  }
}

void loop() {  
  while(client.connected()){
    if(client.available()){
      char c = client.read();
      Serial.print(c);  
    }
  }
}

Now when I upload the sketch, and the data is successfully sent to the remote server, the sensor.php page will display the sensor values on a web browser.

That’s it! For the next part of this series, I will show you another way of sending and receiving data from a remote server still using the ENC28J60 ethernet shield.

Check Also

moving average filter

Implementing an 8-point Moving Average Filter

If you read sensors using microcontrollers before, you have dealt with data that is always …

Leave a Reply

Your email address will not be published. Required fields are marked *