I am working with the NodeMCU V3 module. Whenever I try to make an http request to my server, the module crashes.
Here's the code:
void setup() {
WiFi.begin("wifi-name", "wifi-password");
while (WiFi.status() != WL_CONNECTED) { //Wait for the WiFI to connect }
}
void loop() {
HTTPClient http;
WiFiClient client;
http.begin( client, "server-address" );
int httpCode = http.GET();
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
delay( 1000 );
}
Here's the result, as seen in the serial monitor:
200
["JSON response from the server"]
Exception (28):
epc1=0x40212e82 epc2=0x00000000 epc3=0x00000000 excvaddr=0x000001b6 depc=0x00000000
>>>stack>>>
ctx: cont
sp: 3ffffc90 end: 3fffffc0 offset: 01a0
3ffffe30: 00000000 4bc6a7f0 0000333f 3ffee5f8
3ffffe40: 00000000 00000000 4bc6a7f0 00000000
[...]
3fffffb0: feefeffe feefeffe 3ffe84e8 40100c41
<<<stack<<<
The strange thing is that it retrieves the response from the server correctly, but then, about one second later, it spits out the exception to the serial monitor and resets. At first I thought it could be because I am running ESP8266WebServer at the same time, but it still crashes even when I run the most basic example I could find on the internet. I tried compiling the same code on the Arduino IDE instead of PlatformIO, or even using a different NodeMCU, to no avail.
EDIT: After playing around a bit more, it seems like setting the delay to at least 10 seconds makes the NodeMCU crash after 3 requests instead of after the first one. Could it be that it's memory overflows after a few requests? Am I missing a crucial part that should prepare the ESP8266 for a new request?
There is no need to re-create the WiFi and HTTP clients in the loop() over and over again. You can declare them once globally. Here's a stable version of this simple sketch:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPHTTPClient.h>
HTTPClient http;
WiFiClient client;
void setup() {
Serial.begin(115200);
Serial.println();
WiFi.begin("****", "****");
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("done.");
}
void loop() {
http.begin(client, "http://httpbin.org/get"); // <1KB payload
// http.begin(client, "http://www.geekstips.com/esp8266-arduino-tutorial-iot-code-example/"); // 30KB payload
int httpCode = http.GET();
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
delay(1000);
}
The reported free heap is very stable over time.
Please take note of the second URL I added for testing in the commented line. That http.getString() is convenient and works well for small resources but yields unexpected i.e. wrong results for larger resources - you only see a small fraction of the body printed to the console.
For larger payloads you should use the low-level WiFiClient directly and read/parse the response line-by-line or character-by-character. See the documentation at https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-examples.html for a template.
void loop()
{
WiFiClient client;
Serial.printf("\n[Connecting to %s ... ", host);
if (client.connect(host, 80))
{
Serial.println("connected]");
Serial.println("[Sending a request]");
client.print(String("GET /") + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n" +
"\r\n"
);
Serial.println("[Response:]");
while (client.connected() || client.available())
{
if (client.available())
{
String line = client.readStringUntil('\n');
Serial.println(line);
}
}
client.stop();
Serial.println("\n[Disconnected]");
}
else
{
Serial.println("connection failed!]");
client.stop();
}
delay(5000);
}
Related
I am trying to fetch some details from an API endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc). But everytime it is returning false (-1). When I GET the endpoint on my browser it is just workign fin, returning 200.
http.GET() returns -1
serial monitor putput
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Wire.h>
WiFiClient wifiClient;
void setup() {
Serial.begin(9600);
WiFi.begin("56", "emayush56");
while(WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print("..");
}
Serial.println();
Serial.println("NodeMCU is connected!");
Serial.println(WiFi.localIP());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(wifiClient, "https://bitcoin-ethereum-price-test.vercel.app/btc");
int httpCode = http.GET();
Serial.println("*** RESPONSE STATUS ***");
Serial.println(httpCode);
if (httpCode > 0) {
String payload = http.getString();
Serial.println(payload);
}
http.end();
}
delay(3000);
}
I think either I am doing something wrong with http.begin() or something else. http.begin() can be called in two different ways:
type1:
bool begin(WiFiClient &client, const String& url);
type2:
bool begin(WiFiClient &client, const String& host, uint16_t port, const String& uri = "/", bool https = false);
I have tried with both of them - first by passing directly the WifiClient object and the URL (type 1), and then (type2) by passing the WiFiClient object and other parameters.
If my main api endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc) is returnig 200 then why http.GET() is returning false? Please help me identify the issue.
You're making an HTTP request to an HTTPS API. You will need to use a certificate's sha1 fingerprint. You can get the fingerprint in chrome by clicking on the little lock by the beginning of the URL, go to "Connection is secure" option then "Certificate is valid" and it'll show you some info about the certificate with the keys at the bottom.
Here is some example code I found which uses HTTPS with the HTTPClient library:\
void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTPS] begin...\n");
http.begin("https://some.secure_server.com/auth/authorise", "2F 2A BB 23 6B 03 89 76 E6 4C B8 36 E4 A6 BF 84 3D DA D3 9F");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.POST("user_id=mylogin&user_password=this%20is%20my%20%24ecret%20pa%24%24word");
if (httpCode > 0) {
http.writeToStream(&Serial);
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] ... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
delay(10000);
}
I am trying to send data to a web app using the TCP connection of a SIM808 that is connected to my NodeMcu. Everything appears to work fine, connection is perfect but at the send part, the post request does not execute fully.
below is my code and output
please help check the http_cmd line. In my output, after the content is shown in the output I am suppose to see something like Recv: ### bytes but instead I get ☐fetch over
#include <ESP8266WiFi.h>
#include <DFRobot_sim808.h>
#include <sim808.h>
#include <SoftwareSerial.h>
DFRobot_SIM808 sim808(&Serial);
char http_cmd[] = "POST /tracker/ HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: 34\r\nHost: haul1.herokuapp.com\r\n\r\n{ \"trackerId\": \"2222\",\"height\": \"42\" }";
char buffer[512];
void setup(){
//mySerial.begin(9600);
Serial.begin(9600);
//******** Initialize sim808 module *************
while(!sim808.init()) {
delay(1000);
Serial.print("Sim808 init error\r\n");
}
delay(3000);
//*********** Attempt DHCP *******************
while(!sim808.join()) {
Serial.println("Sim808 join network error");
delay(2000);
}
//************ Successful DHCP ****************
Serial.print("IP Address is ");
Serial.println(sim808.getIPAddress());
//*********** Establish a TCP connection ************
if(!sim808.connect(TCP,"haul.herokuapp.com", 80)) {
Serial.println("Connect error");
}else{
Serial.println("Connect haul.herokuapp.com success");
}
//*********** Send a GET request *****************
Serial.println("waiting to fetch...");
sim808.send(http_cmd, sizeof(http_cmd)-1);
while (true) {
int ret = sim808.recv(buffer, sizeof(buffer)-1);
if (ret <= 0){
Serial.println("fetch over...");
break;
}
buffer[ret] = '\0';
Serial.print("Recv: ");
Serial.print(ret);
Serial.print(" bytes: ");
Serial.println(buffer);
break;
}
//************* Close TCP or UDP connections **********
sim808.close();
//*** Disconnect wireless connection, Close Moving Scene *******
sim808.disconnect();
}
void loop(){
}
OUTPUT:
OUTPUT from Serial Monitor
Sim808 init error
AT
Sim808 init error
AT
AT+CFUN=1
AT+CPIN?
AT+CSTT="","",""
AT+CIICR
AT+CIFSR
IP Address is 10.10.124.205
AT+CIPSTART="TCP", “haul.herokuapp.com”, 80
Connect haul.herokuapp.com success
waiting to fetch...
AT+CIPSEND=145
POST /tracker/ HTTP/1.1
Content—Type: application/json
Content—Length: 34
Host: haul.herokuapp.com
{"trackerId": "2222","height": "42"}☐fetch over...
AT+CIPSTATUS
AT+CIPSHUT
I am making a alert device on my node mcu board to report any orders made by customers on my application. The nodemcu should access the network using wifi and call the rest api. I tried researching many sites and modified the code several times, but the response is always -1, connection refused.
tried doing
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
ESP8266WiFiMulti WiFiMulti;
void setup() {
Serial.begin(9600);
// Serial.setDebugOutput(true);
Serial.println();
Serial.println();
Serial.println();
for (uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
WiFi.mode(WIFI_STA);
WiFiMulti.addAP("----", "----");
}
void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
WiFiClient client;
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if (http.begin(client, "http://34.87.116.113:80/api/v1/iot/Notify/poll")) { // HTTP
http.setAuthorization("admin", "admin123!");
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP} Unable to connect\n");
}
}
delay(5000);
}
I am trying to access a simple web page running in my Rpi-server using ESP8266 and Arduino.
I have refereed this similar SO question , but it's not the solution for my problem.
Here is my current Arduino Code :
#include "WiFiEsp.h"
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(2,3); // RX, TX
#endif
char ssid[] = "RPi"; // your network SSID (name)
char pass[] = "raspberry"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
char server[] = "192.168.50.1";
// Initialize the Ethernet client object
WiFiEspClient client;
void setup()
{
// initialize serial for debugging
Serial.begin(9600);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
// check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data
Serial.println("You're connected to the network");
printWifiStatus();
Serial.println();
Serial.println("Starting connection to server...");
// if you get a connection, report back via serial
if (client.connect(server, 80)) {
Serial.println("Connected to server");
// Make a HTTP request
client.println("GET /simple.html HTTP/1.1");
client.println("Host: 192.168.50.1");
client.println("Connection: close");
client.println();
}
}
void loop()
{
while (client.available()) {
char c = client.read();
Serial.write(c);
}
// if the server's disconnected, stop the client
if (!client.connected()) {
Serial.println();
Serial.println("Disconnecting from server...");
client.stop();
// do nothing forevermore
while (true);
}
void printWifiStatus()
{
// print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength
long rssi = WiFi.RSSI();
Serial.print("Signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
Output:
Starting connection to server...
[WiFiEsp] Connecting to 192.168.50.1
Connected to server
[WiFiEsp] Data packet send error (2)
[WiFiEsp] Failed to write to socket 3
[WiFiEsp] Disconnecting 3
My simple.html looks like this.
<html>
<body>
<p>1</p>
</body>
</html>
}
I accessed to this page from web browser and it shows the content properly.
What is missing here?
Thanks in advance.
Try this line in your code
client.print("GET /simple.html HTTP/1.0\r\n\r\n");
I am trying to make a wireless light control device (on/off/dimming) using an Arduino, an Android app, and a router.
I am setting the Arduino to a static IP 192.168.1.2 using the router. I am sending strings ("1"-off, "2"-decrease brightness, "3"-increase brightness, "4"-on) from the Android app to the IP address 192.168.1.2. I have connected the Arduino to the Internet using the Arduino Wi-Fi shield and set up the WifiServer using the following code:
char ssid[] = "NAME"; // Your network SSID (name)
char pass[] = "PASS"; // Your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // Your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(23);
boolean alreadyConnected = false; // Whether or not the client was connected previously.
void setup() {
// Start serial port:
Serial.begin(9600);
// Attempt to connect to Wi-Fi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// Wait 10 seconds for connection:
delay(10000);
}
// Start the server:
server.begin();
// You're connected now, so print out the status:
printWifiStatus();
}
The main problem I am having is how to accept and print out the strings from the Android device. The current code I have to do this is:
// Listen for incoming clients
WiFiClient client = server.available();
if (client) {
// An HTTP request ends with a blank line
boolean newLine = true;
String line = "";
while (client.connected() && client.available()) {
char c = client.read();
Serial.print(c);
// If you've gotten to the end of the line (received a newline
// character) and the line is blank, the HTTP request has ended,
// so you can send a reply.
if (c == '\n' && newLine) {
// Send a standard HTTP response header
//client.println("HTTP/1.1 200 OK");
//client.println("Content-Type: text/html");
//client.println();
}
if (c == '\n') {
// You're starting a new line
newLine = true;
Serial.println(line);
line = "";
}
else if (c != '\r') {
// You've gotten a character on the current line
newLine = false;
line += c;
}
}
Serial.println(line);
// Give the web browser time to receive the data
delay(1);
// Close the connection:
//client.stop();
}
}
I am basing this code off of the blog post Android Arduino Switch with a TinyWebDB hack, but this code is for an Ethernet shield. The Android app was made using the MIT App Inventor, which is similar to the one found the blog post.
TLDR, how can I get the strings using the Arduino Wi-Fi shield?
You can read the characters into a full string instead of reading each individual character into the serial monitor as in your example above.
In your example, this bit of code would read each character from the client TCP session and print it to the serial monitor, thus displaying the HTTP requests in the serial console.
char c = client.read();
Serial.print(c);
Try something like this instead. Declare a string named "readString" before your setup() function in the Arduino sketch like this:
String readString;
void setup() {
//setup code
}
void loop() {
// Try this when you're reading inside the while client.connected loop instead of the above:
if (readString.length() < 100) {
readString += c;
Serial.print(c);
}
Here is a working example of the loop():
void loop() {
// Listen for incoming clients
WiFiClient client = server.available();
if (client) {
Serial.println("new client");
// An HTTP request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
//Serial.write(c);
// If you've gotten to the end of the line (received a newline
// character) and the line is blank, the HTTP request has ended,
// so you can send a reply.
if (readString.length() < 100) {
readString += c;
Serial.print(c);
}
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println();
client.println("<!DOCTYPE HTML>");
//send the HTML stuff
client.println("<html><head><title>Admin Web</title><style type=\"text/css\">");
client.println("body { font-family: sans-serif }");
client.println("h1 { font-size: 14pt; }");
client.println("p { font-size: 10pt; }");
client.println("a { color: #2020FF; }");
client.println("</style>");
client.println("</head><body text=\"#A0A0A0\" bgcolor=\"#080808\">");
client.println("<h1>Arduino Control Panel</h1><br/>");
client.println("<form method=\"link\" action=\"/unlockdoor\"><input type=\"submit\" value=\"Unlock Door!\"></form>");
client.println("<br/>");
client.println("</body></html>");
break;
}
if (c == '\n') {
// You're starting a new line.
currentLineIsBlank = true;
}
else if (c != '\r') {
// You've gotten a character on the current line.
currentLineIsBlank = false;
}
}
}
// Give the web browser time to receive the data.
delay(1);
// Close the connection:
client.stop();
Serial.println("client disonnected");
if (readString.indexOf("/unlockdoor") > 0)
{
unlockdoor();
Serial.println("Unlocked the door!");
}
readString = "";
}