我正在尝试在外部托管于 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/