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);
}
Related
I am currently developing a project where I want esp8266 to send data to Blazor Server App which is hosted on server, but the problem is the Post request to Blazor's server app api keeps returning error code 415.
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
const String ssid="";
const String password="";
const String url="http://raspberrypiproject.com/api/values/1";
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,password);
Serial.println();
Serial.print("Connecting");
while(WiFi.status()!=WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("Connected to ");
Serial.print(WiFi.SSID());
}
void loop() {
if(WiFi.status()==WL_CONNECTED)
{
WiFiClient client;
HTTPClient http;
if(http.begin(client,url))
{
int code=http.GET();
if(code>0)
{
Serial.println(http.getString());
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
Serial.println(http.POST("hellofromEsp8266"));
}
}
}
}
This is my esp8266 code. In the net I found that the cause of the problem is the Content-Type of "http.addHeader("Content-Type", "application/x-www-form-urlencoded")" and the only change in the response code is when I change it to "multipart/form-data" and it returns error code 400. Is my problem in the client or in Blazor Server.
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);
}
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'm creating a fish feeder with SG90 servo and NodeMCU
I used this sketch:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h>
// Update these with values suitable for your network.
const char* ssid = "your_wifi_hotspot";
const char* password = "your_wifi_password";
const char* mqtt_server = "broker.mqttdashboard.com";
//const char* mqtt_server = "iot.eclipse.org";
Servo myservo; // create servo object to control a servo
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(100);
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Command from MQTT broker is : [");
Serial.print(topic);
for(int i=0;i<length;i++)
{
if((int)payload[i]>194||(int)payload[i]<0)
break;
myservo.write((int)payload[i]); // tell servo to go to position in variable '(int)payload[i]'
}
}//end callback
void reconnect() {
// Loop until we're reconnected
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
if (client.connect(clientId.c_str()))
{
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe("OsoyooCommand");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
myservo.attach(D1); // attaches the servo on pin D1 to the servo object
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
The servo is working when I use MQTTBox in order to send a payload as "Decimal Array", it is however is giving me a hard time when I send payload as JSON string.
If I send "Decimal Array" 1 it does turn Servo to position 1, however if I simply send 1 as a payload as a string it moves Servo to position 49.
If I send payload as 2 it moves to position 50.
If I send payload as 10 then position is 4948
looks like position of 1 and position of 0 at the same time.
My ultimate goal is to send those payloads via HomeAssistant which are sent as string or JSON, however I don't find a correct solution at the moment.
I would highly appreciate any help or solution.
MQTT payloads are UTF-8 encoded so the Arduino PubSubClient library treats the payload as an array of uint8_t.
If you want to send and receive JSON then you can use the ArduinoJson library to parse a JSON payload. So assuming a JSON payload like:
{
"position": 123
}
Then you can implement a callback such as:
#include <ArduinoJson.h>
// Assuming a fixed sized JSON buffer
StaticJsonBuffer<200> jsonBuffer;
void callback(char* topic, byte* payload, unsigned int length)
{
JsonObject& root = jsonBuffer.parseObject(payload);
if (root.success() && root.is<JsonObject>())
{
int position = root.as<JsonObject>().get<int>("position");
myservo.write(position);
}
}
Looks like the motor is taking the position of the ASCII equivalent of the number when you send it as a string.
i.e.
ASCII equivalent of the character '1' in 49 in decimal
ASCII equivalent of the character '2' in 50 in decimal
Try sending the character 'a', the motor will go to 97.
If you want to send a string, you will have to change the following code:
for(int i=0;i<length;i++)
{
if((int)payload[i]>194||(int)payload[i]<0)
break;
myservo.write((int)payload[i]); // tell servo to go to position in variable '(int)payload[i]'
}
to:
int location=String((char*)payload).toInt()
if((location>194)||(location<0))
return;
myservo.write(location);
This is ESP8266 code to turn ON/OFF an LED. I'm using the Arduino IDE built-in example code. The LED is working properly but I want to send HTTP requests to my locally-hosted web site (which send emails) but it's not working.
Connected with my local Wifi
Assigned a static IP
When I hit 192.168.1.101/gpio/1(Led ON)
When I hit 192.168.1.101/gpio/0(Led OFF) It's working but unable to hit my web site.
When I hit 192.168.1.101/gpio/1 then it should hit my locally-hosted URL (192.168.1.100/home/ardchk)
Kindly help me to sort out this issue.
#include <ESP8266WiFi.h>
const char* ssid = "SMART";
const char* password = "123456789";
const char* host = "192.168.1.100"; // Your domain
IPAddress ip(192, 168, 1, 101); // where xx is the desired IP Address
IPAddress gateway(192, 168, 1, 1); // set gateway to match your network
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
// prepare GPIO3
pinMode(3, OUTPUT);
digitalWrite(3, 0);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.config(ip,gateway,subnet);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()) {
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.println(req);
// Match the request
int val;
if (req.indexOf("/gpio/0") != -1) {
val = 0;
if (client.connect(host, 80)) {
//starts client connection, checks for connection
Serial.println("connected to website/server");
client.println("GET /home/ardchk HTTP/1.1"); //Send data
client.println("Host: 192.168.1.100");
Serial.println("Email Sended");
client.println("Connection: close");
//close 1.1 persistent connection
client.println(); //end of get request
}
} else if (req.indexOf("/gpio/1") != -1) {
val = 1;
} else {
Serial.println("invalid request");
client.stop();
return;
}
// Set GPIO2 according to the request
digitalWrite(3, val);
client.flush();
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
s += (val)?"high":"low";
s += "</html>\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("Client disconnected");
// The client will actually be disconnected
// when the function returns and 'client' object is destroyed
}
Based on your question/comment, I am assuming that client.connect(host, 80) is returning false.
I believe you are unable to connect to your host because your are trying to connect twice with the same client.
Your code looks like this:
// returns an already connected client, if available
WiFiClient client = server.available()
//...
if (client.connect(host, 80)) {/*...*/}
You see, you are using the already connected client to attempt to connect to your host. Instead, try creating a separate WiFiClient for that job:
WiFiClient requesting_client = server.available();
//...
if (req.indexOf("/gpio/0") != -1) {
val = 0;
// create a fresh, new client
WiFiClient emailing_client;
if (emailing_client.connect(host, 80)) {
// ...
// don't forget that you need to close this client as well!
emailing_client.stop();
}
Hope this helps!