Arduino Uno+ESP01 module HTTP request issue - arduino

I have been working with my Arduino Uno board and ESP01 module. My goal is to send an HTTP request to a remote server and fetch the last entry of a remote data base. This entry is the state of a remote toggle button which can be modified through a web page located on a remote server. I'm using AT commands.
To check the state of the toggle button HTTP requests are sent every second from Arduino Uno.
The Arduino sketch that I wrote configures the ESP01, connects it to wifi, and sends the HTTP request.
Arduino sketch:
#include <SoftwareSerial.h>
SoftwareSerial SerialESP8266(2,3); // RX, TX
String server = "someServer";
String cadena=""; //to store HTTP request
void setup() {
SerialESP8266.begin(9600);
Serial.begin(9600);
SerialESP8266.setTimeout(5000);
//checking the ESP8266 response
SerialESP8266.println("AT");
if(SerialESP8266.find("OK"))
Serial.println("AT OK");
else
Serial.println("Error on ESP8266");
//ESP8266 in STA mode.
SerialESP8266.println("AT+CWMODE=1");
if(SerialESP8266.find("OK"))
Serial.println("ESP8266 on STATION mode...");
//Connecting to wifi
SerialESP8266.println("AT+CWJAP=\"mySSID\",\"somePassword\"");
Serial.println("Connnecting...");
SerialESP8266.setTimeout(10000); //waiting for connection
if(SerialESP8266.find("OK"))
Serial.println("WIFI OK");
else
Serial.println("Unable to connect...");
SerialESP8266.setTimeout(2000);
//Disable multiple connections
SerialESP8266.println("AT+CIPMUX=0");
if(SerialESP8266.find("OK"))
Serial.println("Multiple connections disabled");
}
void loop() {
SerialESP8266.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");
//connecting to server
if(SerialESP8266.find("OK")) {
Serial.println();
Serial.println();
Serial.println();
Serial.println("Server connection successful...");
//Armamos el encabezado de la peticion http
String peticionHTTP= "GET /readLast.php";
peticionHTTP=peticionHTTP+" HTTP/1.1\r\n";
peticionHTTP=peticionHTTP+"Host: someserver\r\n\r\n";
peticionHTTP=peticionHTTP+"Host: localhost\r\n\r\n";
//Sending the length of the HTTP request
SerialESP8266.print("AT+CIPSEND=");
SerialESP8266.println(peticionHTTP.length());
//waiting for ">" for sending HTTP request
if(SerialESP8266.find(">")) {
//we can send the HTTP request when > is displayed
Serial.println("Sending HTTP request. . .");
SerialESP8266.println(peticionHTTP);
if(SerialESP8266.find("SEND OK")) {
Serial.println("HTTP request sent...:");
Serial.println();
Serial.println("On stand by...");
boolean fin_respuesta=false;
long tiempo_inicio=millis();
cadena="";
while(fin_respuesta==false) {
while(SerialESP8266.available()>0) {
char c=SerialESP8266.read();
Serial.write(c);
cadena.concat(c); //store the request string on "cadena"
}
//terminate if "cadena" length is greater than 3500
if(cadena.length()>3500) {
Serial.println("The request exceeded the maximum length...");
SerialESP8266.println("AT+CIPCLOSE");
if( SerialESP8266.find("OK"))
Serial.println("Connection terminated...");
fin_respuesta=true;
}
if((millis()-tiempo_inicio)>10000) {
//Terminate if connection time exceeded the maximum
Serial.println("Connection time exceeded...");
SerialESP8266.println("AT+CIPCLOSE");
if( SerialESP8266.find("OK"))
Serial.println("Connection terminated");
fin_respuesta=true;
}
if(cadena.indexOf("CLOSED")>0) {
Serial.println();
Serial.println("String OK, connection terminated");
fin_respuesta=true;
}
}
} else {
Serial.println("error on HTTP request.....");
}
}
} else {
Serial.println("Unable to find the server....");
}
delay(1000); //1 second delay before new loop
}
The HTTP requests (GET request) is handled by readLast.php on the server, which connects to the database and returns the last state of the toggle button. Two states are possible: encender (TURN ON) or apagar (TURN OFF).
readLast.php
<?php
$servername = "host";
$username = "user"; // username for your database
$password = "password";
$dbname = "database"; // Name of database
$now = new DateTime();
$CRLF = "\n\r";
$conn = mysqli_connect("localhost", "user", "password");
if (!$conn) {
die('Could not connect: ' . mysqli_error($conn));
}
$con_result = mysqli_select_db($conn,"database");
if(!$con_result) {
die('Could not connect to specific database: ' . mysqli_error($conn));
}
$result = mysqli_query($conn, "SELECT accion from `datatable` where id = (select MAX(id) from datatable)");
if (!$result) {
die('Invalid query: ' . mysqli_error($conn));
}
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo "accion=" . $row["accion"];
}
mysqli_close($conn);
?>
The first HTTP request returns the state of toggle button correctly. But the next HTTP requests return BAD HTTP REQUEST:
IPD,298:HTTP/1.1 200 OK
Date: Fri, 01 Dec 2017 01:40:56 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: awex
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Request-ID: cf44e42dbd53cb7cb5456e4b70e3399d
10
accion: encender
+IPD,5:0
+IPD,428:HTTP/1.1 400 Bad Request
Date: Fri, 01 Dec 2017 01:40:56 GMT
Content-Type: text/html
Content-Length: 170
Connection: close
Server: awex
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Request-ID: d8ffa7b4eece5d1e88c7786fea5ace9f
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>openresty</center>
</body>
</html>
CLOSED
What I am doing wrong?

I had the same problem, but was able to fix it with:
while(SerialESP8266.available()>0) {
char c=SerialESP8266.read();
Serial.write(c);
cadena.concat(c); //store the request string on "cadena"
if (cadena.length() > 50) cadena = "";
}
The problem is due to the limit of string.indexof();
Max characters supported are 170, anything larger will not work.

Related

Arduino HTTP POST to Firebase

I have a ESP32 SIM800L module which I would like to send data to a firebase database. I can connect my SIM to GPRS but I am completely stuck on how to send any data via a post request with Arduino. The documents say to use curl for this purpose. So how do I formulate the below code client code to conform to that?
Just a snippet of the library I use
#include <TinyGsmClient.h>
TinyGsmClient client(modem);
const char server[] = "https://mydatabaseUrl";
const int port = 80;
And this is my Post request.
Serial.println("start POST request");
client.print("POST /gps.json HTTP/1.1\r\n");
client.print(String("Host: ") + server + "\r\n");
client.println("Connection: close");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(postData.length());
client.println();
client.println(postData);
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 10000L) {
// Print available data (HTTP response from server)
while (client.available()) {
char c = client.read();
SerialMon.print(c);
timeout = millis();
}
}
SerialMon.println();
client.stop();
This is the output I get
19:30:29.488 -> HTTP/1.1 400 Bad Request
19:30:29.488 -> Content-Length: 54
19:30:29.488 -> Content-Type: text/html; charset=UTF-8
19:30:29.488 -> Date: Fri, 28 May 2021 17:30:29 GMT
19:30:29.488 -> Connection: close
19:30:29.488 ->
19:30:29.488 -> <html><title>Error 400 (Bad Request)!!1</title></html>

GPRS module sendTCPData returns 403 Forbidden server error

I'm trying to fetch data from web server using Arduino Uno. I'm using SIM800L module to connect via GPRS. Following is the code I used to connect to web server.
#include <gprs.h>
#include <SoftwareSerial.h>
char http_cmd[] = "GET canopussl.com/info.php HTTP/1.1\r\n\r\n";
char buffer[512];
GPRS gprs;
void setup() {
Serial.begin(9600);
while(!Serial);
Serial.println("GPRS - HTTP Connection Test...");
gprs.preInit();
while(0 != gprs.init()) {
delay(1000);
Serial.println("init error");
}
while(!gprs.join("dialogbb")) { //change "cmnet" to your own APN
Serial.println("Error joining GPRS network");
delay(2000);
}
// successful DHCP
Serial.print("IP Address is ");
Serial.println(gprs.getIPAddress());
Serial.println("Init success, connecting to canopussl.com ...");
if(0 == gprs.connectTCP("canopussl.com", 80)) {
Serial.println("Successfully connected to canopussl.com!");
}else{
Serial.println("connect error");
while(1);
}
Serial.println("waiting to fetch...");
if(0 == gprs.sendTCPData(http_cmd))
{
gprs.serialDebug();
}
gprs.closeTCP();
gprs.shutTCP();
Serial.println("close");
}
void loop() {
}
The output was this.
GPRS - HTTP Connection Test...
IP Address is 10.84.3.49
Init success, connecting to canopussl.com ...
Successfully connected to canopussl.com!
waiting to fetch...
HTTP/1.0 403 Forbidden
Cache-Control: no-cache
Connection: close
Content-Type: text/html
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
CLOSED
How I have to modify the HTTP header to receive the normal output from server?
You are not sending the mandatory Host header.
Your HTTP request should look like:
char http_cmd[] = "GET /info.php HTTP/1.1\r\nHost: canopussl.com\r\n\r\n";

Arduino ethernet shield doesn't send data - REST API

I have a little problem with function GET function of HTTP. The program reads ID number, and after enter(new line), it should get data from REST API. Problem is that I have to press enter twice for data from API. Here is code
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x90, 0x02, 0xBA, 0xEF, 0xCA, 0x33 };
char server[] = "xxx.xx";
EthernetClient client;
char tmp;
char buffer[30];
int bufferCounter = 0;
void setup() {
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
delay(1000);
Serial.println("Ready");
}
void getData(char* num ){
Serial.println("connecting...");
if (client.connect(server, 80)) {
Serial.println("connected");
client.print("GET /api/id/");
client.print(num);
client.println("/?format=json HTTP/1.1");
client.println("Host: xxx.xx");
client.println("Authorization: Token xxxxxxxxxxxxxxxxxxxxx");
client.println("Connection: close");
client.println();
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
while (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
}
void loop() {
if (Serial.available() > 0) {
tmp = Serial.read();
if(tmp == '\n'){
buffer[bufferCounter] = 0;
bufferCounter = 0;
Serial.println(buffer);
getData(buffer);
}
else{
buffer[bufferCounter] = tmp;
bufferCounter++;
}
}
}
On the serial link I get this message. At first
Ready
when I write there 35 and press enter I get this
35
connecting...
connected
then I have to press enter again, and finally I get the correct data but with connection failed and I dont know why
connecting...
connection failed
HTTP/1.1 404 NOT FOUND
Date: Tue, 22 Nov 2016 16:18:18 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: close
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Vary: Accept, Cookie
18
{"detail":"not found."}
0
disconnecting.
Could someone help me, where is the problem? Thank you.

Ethernet shield can't connect server with keep alive connection

I want to use Ethernet shield to send/get data from my Apche server (localhost).
Ethernet(or Esp8266) ======(request.php by post method)==>>> server
Ethernet(or Esp8266) <<<=====(respond header and data)==== server
i send header to server to get data.
In my header:
If i use connection: close. This way seems ok. But when i use connection: keep-alive. it can't connect or get any data till connection time out.
This is my header and way to send my data to server:
String httpRequest(String data){
String result="";
if(client.connect(server, 80)){
Serial.println("connected");
client.println("POST /pihome1/getStatus.php HTTP/1.1");
client.println("Host: localhost");
client.println("Accept: *" "/" "*");
client.println("Content-Length: " + String(data.length()));
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("Connection: keep-alive");
client.println();
client.print(data);
}
else {
//if you didn't get a connection to the server:
Serial.println("connection failed");
}
//Reading data
unsigned long start = millis();
int timeout = 2000;
while (millis() - start < timeout){
while (client.available()) {
char c = client.read();
result += c;
}
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.flush();
client.stop();
}
return result;
}
After the first success it can't connect till time out connect.
========Request to server=========
connected
HTTP/1.1 200 OK
Date: Sun, 04 Oct 2015 08:03:46 GMT
Server: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16
X-Powered-By: PHP/5.4.16
Content-Length: 10
Keep-Alive: timeout=50, max=100
Connection: Keep-Alive
Content-Type: text/html
1&1eos
========End of request=========
========Request to server=========
connection failed
========End of request========
Please tell me what problems?

Arduino Getting Data From Web Page

I'm trying to connect my Arduino uno + Ethernet shield to a php script that gets a value from a database and then is sent back which then is displayed on a serial monitor. It works, it connects successfully and i get the value sent back however I'm having trouble displaying it on the serial monitor. It should just display what the server sends however it doesn't. Any one can help?
The Serial Output : It should just output "The Value", however there are numbers that shouldn't be there. If i output this to a LCD monitor i can't have them numbers present.
connecting...
connected
HTTP/1.1 200 OK
Server: cloudflare-nginx
Date: Sat, 04 Jan 2014 15:36:51 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
Set-Cookie: __cfduid=dcef101052b82760c1a2de019e6b076141388849811461; expires=Mon, 23-Dec-2019 23:50:00 GMT; path=/; domain=.linku.biz; HttpOnly
X-Powered-By: PHP/5.3.27
CF-RAY: e7901b6dec606e2
4
The
5
Value
0
disconnecting.
PHP Script
<?php
echo 'The Value';
?>
Arduino Script
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "www.linku.biz"; // name address for Google (using DNS)
// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192,168,0,177);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /arduino.php HTTP/1.1");
client.println("Host: www.linku.biz");
client.println("Connection: close");
client.println();
}
else {
// kf you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
while(true);
}
}
Don't know if this helps, but notice that the numbers are the count of available chars which are read out. 4 "The " and 5 "value"
I would expect that client.available returns the 4 and 5 values just after those chars are received. How they got converted to ASCI "4" and "5" and printed, I have no idea.
I parse data by this code
String readString;
//gets byte from ethernet buffer
readString += client.read(); //places captured byte in
//parse readString for request
index = readString.indexOf("text"); //finds location of first "text"
data_want = readString.substring(index+some char, index+some char); //captures data String
Serial.println(data_wand);

Resources