【问题标题】:How can I send get or post request to Heroku API using ESP8266?如何使用 ESP8266 向 Heroku API 发送 get 或 post 请求?
【发布时间】:2022-02-13 04:06:16
【问题描述】:

目前我已经使用 nodejs 构建了一个简单的 api 并将其部署在 heroku 中。 Heroku 是一个安全网站,所以我在我的 nodemcu 程序中使用 WiFiClientSecure.h 来连接到 api。但它会返回这样的错误。

connecting to WIFI
....
WiFi connected
IP address: 
xxxxxxxxxxx
connecting to api71.herokuapp.com


 CUT HERE FOR EXCEPTION DECODER ---------------

Exception (9):
epc1=0x40207acc epc2=0x00000000 epc3=0x00000000 excvaddr=0xfeefeffe depc=0x00000000
>>>stack>>>

ctx: cont
sp: 3ffffc80 end: 3fffffc0 offset: 0190
3ffffe10:  3ffe87d5 3fff11bc 3ffffea0 40203b53  
3ffffe20:  00000124 3ffee784 00000001 40205b14  
3ffffe30:  00000000 00000000 00000000 4020610e  
3ffffe40:  00000000 3ffffea0 3ffef52c 4020281c  
3ffffe50:  3ffee680 00000d50 3ffe86fc 3ffe862b  
3ffffe60:  000001bb 3ffffea0 3ffe87d5 3ffe862b  
3ffffe70:  000001bb 3ffffea0 3ffe87d5 40203d29  
3ffffe80:  40208078 54cac522 40208078 54cac522  
3ffffe90:  3ffe84cc 3ffe84cc 3ffee6a0 40201150  
3ffffea0:  40207f18 00000000 00003a98 feefeffe  
3ffffeb0:  00000000 3ffef52c 3fff11bc 3ffef66c  
3ffffec0:  00000000 00000000 3fff11bc 3fff62c4  
3ffffed0:  3ffef75c 00000000 00000000 00000000  
3ffffee0:  00000000 3fff1f14 3ffef57c 3fff6064  
3ffffef0:  3ffef594 00000000 00000000 00000000  
3fffff00:  00004145 00000255 feef0000 00000000  
3fffff10:  00000000 00000000 00000000 00000000  
3fffff20:  00000000 00000000 feef0000 feefeffe  
3fffff30:  feefeffe feefeffe feefeffe fe00effe  
3fffff40:  00000000 feefeffe 00000000 00000000  
3fffff50:  feefef00 00000000 00000000 feefeffe  
3fffff60:  feefeffe feefeffe feefeffe feefeffe  
3fffff70:  feefeffe feefeffe feefeffe feefeffe  
3fffff80:  feefeffe feefeffe feefeffe feefeffe  
3fffff90:  feefeffe feefeffe feefeffe 3ffee728  
3fffffa0:  3fffdad0 00000000 3ffee6e8 40205c24  
3fffffb0:  feefeffe feefeffe 3ffe84f0 40100b85  
<<<stack<<<

我在 localhost 中检查了我的 api,它工作正常。与安全网站交互存在问题。 Heroku 使用 sha256RSA 签名算法和 sha256 作为签名哈希。 这是我部署的代码

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

const char * ssid = "YOURNETWORK"; 
const char * password = "YOURPASSWORD"; 
const char * host = "api71.herokuapp.com"; 
String path = "/api/courses"; // Path of Server
const int httpsPort = 443; // HTTPS PORT (default: 443)
int refreshtime = 15; // Make new HTTPS request after x seconds


String datarx; // Received data as string
long crontimer;

void setup () {
  delay (1000);
  Serial.begin (115200);
  WiFi.mode (WIFI_OFF);
  delay (1000);
  WiFi.mode (WIFI_STA);
  WiFi.begin (ssid, password);
  Serial.print ("Connecting");
  while (WiFi.status ()! = WL_CONNECTED) {
    delay (500);
    Serial.print (".");
  }
  Serial.print ("Connected:");
  Serial.println (ssid);
}

void loop () {
  if (crontimer <millis () / 1000) {
    crontimer = (millis () / 1000) + refreshtime;
    callhttps (); //
  }
}

void callhttps () {
  WiFiClientSecure httpsClient;
  httpsClient.setTimeout (15000);
  delay (1000);
  int retry = 0;
  while ((! httpsClient.connect (host, httpsPort)) && (retry <15)) {
    delay (100);
    Serial.print (".");
    retry ++;
  }
  if (retry == 15) {
    Serial.println ("Connection failed");
  }
  else {
    Serial.println ("Connected to Server");
  }
  httpsClient.print (String ("GET") + path + 
                    "HTTP / 1.1 \ r \ n" +
                    "Host:" + host +
                    "\ r \ n" + "Connection: close \ r \ n \ r \ n");
  while (httpsClient.connected ()) {
    String line = httpsClient.readStringUntil ('\ n');
    if (line == "\ r") {
      break;
    }
  }
  while (httpsClient.available ()) {
    datarx + = httpsClient.readStringUntil ('\ n');
  }
  Serial.println (datarx);
  datarx = "";
}

有什么理由要连接到这个网站吗?请帮帮我。

【问题讨论】:

  • 使用堆栈跟踪解码器

标签: node.js heroku arduino-esp8266


【解决方案1】:

我使用 http 解决了这个问题。 http://domain.herokuapp.com/api.

另一点是... ESP8266 发送“开始”数据进行发布。 funcition.POST() 只是发送在 begin http 函数中声明的值。

使用“std::unique_ptrBearSSL::WiFiClientSecureclient(new BearSSL::WiFiClientSecure);”你失去了连接,因为这个库使用不同的 RSHA 密钥和 heroku。

在开始之前发送数据,您收到此消息是因为 Arduino 将对象发送到内存中,而不是连接 url。

" 此处为异常解码器 --------------- "。

如果您的服务有同样的错误,您会收到消息:连接失败。

HttpClient和WifiClient在循环中声明,导致内存泄漏和崩溃。

我总结了。

#include //ESP8266核心WiFi库
#include

查看部分代码:

HTTPClient https;    //Declare object of class HTTPClient
WiFiClient client;   // Declare out of loop like a global variable


https.begin(client, "http://domain.herokuapp.com/api?id=xxxx&temp=xx");      
//Specify request destination
    
    https.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header
      
    int httpCode = https.POST(""); //Send the request    
    
    String payload = https.getString(); //Get the response payload

    Serial.print("[HTTP] POST...\n");
    // httpCode will be negative on error
    if (httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      Serial.printf("[HTTP] POST... code: %d\n", httpCode);
      
      // file found at server
      if (httpCode == HTTP_CODE_OK) {
        const String& payload = https.getString();
        Serial.println("received payload:\n<<");
        Serial.println(payload);
        Serial.println(">>");
        https.end();  //Close connection
      }
    } else {
      Serial.print (payload);
      Serial.print (httpCode);
      Serial.println(WiFi.localIP());
      
      Serial.printf("[HTTP] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
      https.end();  //Close connection
    }

【讨论】:

  • 我发现我们可以使用 http 请求,而无需对 heroku 服务器使用 https 请求。
【解决方案2】:

我想出来的是不使用https请求就可以轻松解决问题。

更新后的代码是

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

const char* ssid = "";
const char* password = "";

//Your Domain name with URL path or IP address with path
const char* serverName = "http://iotlightcontrol.herokuapp.com/status/1";


unsigned long timerDelay = 0;

String sensorReadings;
float sensorReadingsArr[3];

void setup() {
  Serial.begin(115200);
  pinMode(D1,OUTPUT);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {
  //Send an HTTP POST request every 10 minutes
  if ((millis() - lastTime) > timerDelay) {
    //Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
              
      sensorReadings = httpGETRequest(serverName);
      //Serial.println(sensorReadings);
      JSONVar myObject = JSON.parse(sensorReadings);
  
      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
    
      Serial.print("JSON object = ");
      Serial.println(myObject);

      int k = int(myObject);
      if(k == 1)
      {
        digitalWrite(D1,HIGH);
        Serial.println("LED ON");
      }
      else if(k == 0){
        digitalWrite(D1,LOW);
        Serial.println("LED OFF");
      }
        
    
      // myObject.keys() can be used to get an array of all the keys in the object
      JSONVar keys = myObject.keys();
      Serial.println(keys);
    
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

String httpGETRequest(const char* serverName) {
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(serverName);
  
  // Send HTTP POST request
  int httpResponseCode = http.GET();
  
  String payload = "{}"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

以上代码是使用我自己的网站(NodeJs作为后端)控制led灯的示例。

【讨论】:

    【解决方案3】:

    有时只是 Serial.print 的缓冲区溢出,如果是这种情况,请使用 ESP 的 JSON 库来解决此问题,或者如果不需要则删除 Serial.print,或者测试是否是不是这样的。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 2018-01-27
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多