curl - 如何在 ESP32 中发布 OTA 的 bin 文件,而无需在网络服务器托管的浏览器中手动打开页面

标签 curl iot esp32 arduino-esp8266 ota

我正在尝试在外部托管于 ESP32 的网络服务器上触发 OTA 更新,并且无需打开网络服务器的浏览器地址。

我见过一些示例,其中如果 ESP 作为客户端连接,则可以实现 OTA 更新操作,但我正在寻找可以将 ESP 仅作为网络服务器的解决方案。 因为,这个 Action 被假设是通过网络触发的,所以出于这个原因,我会很乐意接受如果有任何方法curl、python/JavaScript http方法、节点红色等。

这是在 ESP32 中运行的代码的服务器部分:

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h> 
#include <ESPmDNS.h> 
#include <Update.h> 
#include <WiFiManager.h>  
WebServer server(80);


const char* serverIndex = 
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
   "<input type='file' name='update'>"
        "<input type='submit' value='Update'>"
    "</form>"
 "<div id='prg'>progress: 0%</div>"
 "<script>"
  "$('form').submit(function(e){"
  "e.preventDefault();"
  "var form = $('#upload_form')[0];"
  "var data = new FormData(form);"
  " $.ajax({"
  "url: '/update',"
  "type: 'POST',"
  "data: data,"
  "contentType: false,"
  "processData:false,"
  "xhr: function() {"
  "var xhr = new window.XMLHttpRequest();"
  "xhr.upload.addEventListener('progress', function(evt) {"
  "if (evt.lengthComputable) {"
  "var per = evt.loaded / evt.total;"
  "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  "}"
  "}, false);"
  "window.location.href ='/login';"
  "return xhr;"
  "},"
  "success:function(d, s) {"
  "console.log('successok !')" 
 "},"
 "error: function (a, b, c) {"
 "}"
 "});"
 "});"
 "</script>";

void setup()
{
//redundant parts have been removed intentionally
WiFi.begin(ssid, pass);
int  ct =0;


while (!MDNS.begin(host)) { //http://esp32.local //http://shariq-room.local
    Serial.println("Error setting up MDNS responder!");
    delay(1000);
    ct= ct+1000;

    if (ct>5000) {
      Serial.println("MDNS cannot be set");
      break;
      
    }
  }
  MDNS.addService("http", "tcp", 80);

server.on("/serverIndex", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", serverIndex);
  });
    
        server.on("/update", HTTP_POST, []() {
        server.sendHeader("Connection", "close");
        server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
        ESP.restart();
      }, []() {
        Serial.println("OTA started ");
        HTTPUpload& upload = server.upload();
        if (upload.status == UPLOAD_FILE_START) {
          Serial.printf("Update: %s\n", upload.filename.c_str());
          if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
            Update.printError(Serial);
          }
        } else if (upload.status == UPLOAD_FILE_WRITE) {
          /* flashing firmware to ESP*/
          if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
            Update.printError(Serial);
          }
        } else if (upload.status == UPLOAD_FILE_END) {
          if (Update.end(true)) { //true to set the size to the current progress
            Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
          } else {
            Update.printError(Serial);
          }
        }
      });
      server.begin();
}
void loop()
{
  server.handleClient(); 

   delay(400); 
}
  • 现在,如果我打开,这将允许我选择并选择一个 bin 文件 如果单击“更新”按钮,则获取 localIP 并处理 OTA。
  • 但是当使用任何一个 python 时,相同的“行为”将无法触发它 curl 命令的脚本。从 Chrome 开发者工具的网络部分复制的 curl 命令。

Python脚本在这里。

##python
import requests
data = open("home_automate_inc_ota_v.0.2a.ino.esp32.bin", 'rb').read()
files = {'file': open("home_automate_inc_ota_v.0.2a.ino.esp32.bin", 'rb')}
#headers = {    "Content-Type":"application/binary",}
headers= { 'Accept': 'text/plain'}
print("started")
 upload = requests.post("http://192.168.0.7/update", data=data,headers=headers)
#tried below method too
# final_resp = requests.post("http://192.168.0.7/update", files=files, headers=headers)
print("done");

但是我会在任何一种 post 方法上遇到错误,例如 引发 ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('连接中止。', RemoteDisconnected('远程端关闭连接而无响应'))

curl中尝试时也是如此

curl "http://192.168.0.50/update" ^
  -H "Connection: keep-alive" ^
  -H "Accept: */*" ^
  -H "X-Requested-With: XMLHttpRequest" ^
  -H "User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36" ^
  -H "Content-Type: multipart/form-data; boundary=----#some hidden webkit data#" ^
  -H "Origin: http://192.168.0.50" ^
  -H "Referer: http://192.168.0.50/backup" ^
  -H "Accept-Language: en-US,en;q=0.9" ^
  -H "Cookie: ext_name=#some hidden cookie data#" ^
  --data-raw ^"------#some hidden webkit data#^

Content-Disposition: form-data; name=^\^"update^\^"; filename=^\^"home_automate_inc_ota_v.0.2a.ino.esp32.bin^\^"^

Content-Type: application/octet-stream^

^

^

------WebKitFormBoundaryPtpk4VGDdfwqS932--^

^" ^
  --compressed ^
  --insecure

给出错误为 curl: (52) 服务器的空回复

希望我已经很好地解释了这个问题。如果您需要更多说明,请告诉我。

问候, 沙里克

最佳答案

Romkey建议我所要做的就是从我的请求中删除 header 。 我发现我的 python 代码成功了,但是curl 命令失败了。 这是脚本。

#!Python
import requests
files = {'file': open(r"<full path of the bin file including dir>home_automate_inc_ota_v.0.2a.ino.esp32.bin", 'rb')}

final_resp = requests.post("http://192.168.0.50/update", files=files)

关于curl - 如何在 ESP32 中发布 OTA 的 bin 文件,而无需在网络服务器托管的浏览器中手动打开页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67160638/

相关文章:

c++ - 在 C++ 中使用 STL 的 cURL

python - 可以使用 cURL 访问 JIRA API,但不能使用 Requests

ssl - 带有 AES 的 TLS 或 IPSec 用于物联网安全

android - 如何在 Android 中将 bin 文件传输到支持 Alljoyn 的开发板

c - 为什么我的 ESP32 启动后不断重置?

php - 访问来自 PHP/JQuery.ajax 的传入 PUT 数据以及如何处理它?

json - 让 R Plumber API 在 POST 上使用 JSON

ssl - 物联网设备上更新SHA-1指纹的方法

ios - 如何从 ios 应用程序通过 BLE 打开连接到 arduino 的 LED?

c - ESP 32 中断问题