Prvni ulozeni z chegewara githubu
This commit is contained in:
68
libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino
Normal file
68
libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino
Normal file
@ -0,0 +1,68 @@
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
const char* ssid = "..........";
|
||||
const char* password = "..........";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Booting");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||
Serial.println("Connection Failed! Rebooting...");
|
||||
delay(5000);
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
// Port defaults to 3232
|
||||
// ArduinoOTA.setPort(3232);
|
||||
|
||||
// Hostname defaults to esp3232-[MAC]
|
||||
// ArduinoOTA.setHostname("myesp32");
|
||||
|
||||
// No authentication by default
|
||||
// ArduinoOTA.setPassword("admin");
|
||||
|
||||
// Password can be set with it's md5 value as well
|
||||
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
|
||||
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
|
||||
|
||||
ArduinoOTA
|
||||
.onStart([]() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||
type = "sketch";
|
||||
else // U_SPIFFS
|
||||
type = "filesystem";
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
Serial.println("Start updating " + type);
|
||||
})
|
||||
.onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
})
|
||||
.onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||
})
|
||||
.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
|
||||
ArduinoOTA.begin();
|
||||
|
||||
Serial.println("Ready");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
ArduinoOTA.handle();
|
||||
}
|
169
libraries/ArduinoOTA/examples/OTAWebUpdater/OTAWebUpdater.ino
Normal file
169
libraries/ArduinoOTA/examples/OTAWebUpdater/OTAWebUpdater.ino
Normal file
@ -0,0 +1,169 @@
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <Update.h>
|
||||
|
||||
const char* host = "esp32";
|
||||
const char* ssid = "xxx";
|
||||
const char* password = "xxxx";
|
||||
|
||||
WebServer server(80);
|
||||
|
||||
/*
|
||||
* Login page
|
||||
*/
|
||||
|
||||
const char* loginIndex =
|
||||
"<form name='loginForm'>"
|
||||
"<table width='20%' bgcolor='A09F9F' align='center'>"
|
||||
"<tr>"
|
||||
"<td colspan=2>"
|
||||
"<center><font size=4><b>ESP32 Login Page</b></font></center>"
|
||||
"<br>"
|
||||
"</td>"
|
||||
"<br>"
|
||||
"<br>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td>Username:</td>"
|
||||
"<td><input type='text' size=25 name='userid'><br></td>"
|
||||
"</tr>"
|
||||
"<br>"
|
||||
"<br>"
|
||||
"<tr>"
|
||||
"<td>Password:</td>"
|
||||
"<td><input type='Password' size=25 name='pwd'><br></td>"
|
||||
"<br>"
|
||||
"<br>"
|
||||
"</tr>"
|
||||
"<tr>"
|
||||
"<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
|
||||
"</tr>"
|
||||
"</table>"
|
||||
"</form>"
|
||||
"<script>"
|
||||
"function check(form)"
|
||||
"{"
|
||||
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
|
||||
"{"
|
||||
"window.open('/serverIndex')"
|
||||
"}"
|
||||
"else"
|
||||
"{"
|
||||
" alert('Error Password or Username')/*displays error message*/"
|
||||
"}"
|
||||
"}"
|
||||
"</script>";
|
||||
|
||||
/*
|
||||
* Server Index Page
|
||||
*/
|
||||
|
||||
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);"
|
||||
"return xhr;"
|
||||
"},"
|
||||
"success:function(d, s) {"
|
||||
"console.log('success!')"
|
||||
"},"
|
||||
"error: function (a, b, c) {"
|
||||
"}"
|
||||
"});"
|
||||
"});"
|
||||
"</script>";
|
||||
|
||||
/*
|
||||
* setup function
|
||||
*/
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Connect to WiFi network
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
/*use mdns for host name resolution*/
|
||||
if (!MDNS.begin(host)) { //http://esp32.local
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
Serial.println("mDNS responder started");
|
||||
/*return index page which is stored in serverIndex */
|
||||
server.on("/", HTTP_GET, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", loginIndex);
|
||||
});
|
||||
server.on("/serverIndex", HTTP_GET, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", serverIndex);
|
||||
});
|
||||
/*handling uploading firmware file */
|
||||
server.on("/update", HTTP_POST, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||
ESP.restart();
|
||||
}, []() {
|
||||
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(void) {
|
||||
server.handleClient();
|
||||
delay(1);
|
||||
}
|
26
libraries/ArduinoOTA/keywords.txt
Normal file
26
libraries/ArduinoOTA/keywords.txt
Normal file
@ -0,0 +1,26 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Ultrasound
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ArduinoOTA KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
setup KEYWORD2
|
||||
handle KEYWORD2
|
||||
onStart KEYWORD2
|
||||
onEnd KEYWORD2
|
||||
onError KEYWORD2
|
||||
onProgress KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
9
libraries/ArduinoOTA/library.properties
Normal file
9
libraries/ArduinoOTA/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=ArduinoOTA
|
||||
version=2.0.0
|
||||
author=Ivan Grokhotkov and Hristo Gochkov
|
||||
maintainer=Hristo Gochkov <hristo@espressif.com>
|
||||
sentence=Enables Over The Air upgrades, via wifi and espota.py UDP request/TCP download.
|
||||
paragraph=With this library you can enable your sketch to be upgraded over network. Includes mdns anounces to get discovered by the arduino IDE.
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp32
|
395
libraries/ArduinoOTA/src/ArduinoOTA.cpp
Normal file
395
libraries/ArduinoOTA/src/ArduinoOTA.cpp
Normal file
@ -0,0 +1,395 @@
|
||||
#ifndef LWIP_OPEN_SRC
|
||||
#define LWIP_OPEN_SRC
|
||||
#endif
|
||||
#include <functional>
|
||||
#include <WiFiUdp.h>
|
||||
#include "ArduinoOTA.h"
|
||||
#include "ESPmDNS.h"
|
||||
#include "MD5Builder.h"
|
||||
#include "Update.h"
|
||||
|
||||
|
||||
// #define OTA_DEBUG Serial
|
||||
|
||||
ArduinoOTAClass::ArduinoOTAClass()
|
||||
: _port(0)
|
||||
, _initialized(false)
|
||||
, _rebootOnSuccess(true)
|
||||
, _mdnsEnabled(true)
|
||||
, _state(OTA_IDLE)
|
||||
, _size(0)
|
||||
, _cmd(0)
|
||||
, _ota_port(0)
|
||||
, _ota_timeout(1000)
|
||||
, _start_callback(NULL)
|
||||
, _end_callback(NULL)
|
||||
, _error_callback(NULL)
|
||||
, _progress_callback(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
ArduinoOTAClass::~ArduinoOTAClass(){
|
||||
_udp_ota.stop();
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::onStart(THandlerFunction fn) {
|
||||
_start_callback = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::onEnd(THandlerFunction fn) {
|
||||
_end_callback = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::onProgress(THandlerFunction_Progress fn) {
|
||||
_progress_callback = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::onError(THandlerFunction_Error fn) {
|
||||
_error_callback = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setPort(uint16_t port) {
|
||||
if (!_initialized && !_port && port) {
|
||||
_port = port;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setHostname(const char * hostname) {
|
||||
if (!_initialized && !_hostname.length() && hostname) {
|
||||
_hostname = hostname;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String ArduinoOTAClass::getHostname() {
|
||||
return _hostname;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setPassword(const char * password) {
|
||||
if (!_initialized && !_password.length() && password) {
|
||||
MD5Builder passmd5;
|
||||
passmd5.begin();
|
||||
passmd5.add(password);
|
||||
passmd5.calculate();
|
||||
_password = passmd5.toString();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setPasswordHash(const char * password) {
|
||||
if (!_initialized && !_password.length() && password) {
|
||||
_password = password;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setPartitionLabel(const char * partition_label) {
|
||||
if (!_initialized && !_partition_label.length() && partition_label) {
|
||||
_partition_label = partition_label;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String ArduinoOTAClass::getPartitionLabel() {
|
||||
return _partition_label;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setRebootOnSuccess(bool reboot){
|
||||
_rebootOnSuccess = reboot;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArduinoOTAClass& ArduinoOTAClass::setMdnsEnabled(bool enabled){
|
||||
_mdnsEnabled = enabled;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::begin() {
|
||||
if (_initialized){
|
||||
log_w("already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_port) {
|
||||
_port = 3232;
|
||||
}
|
||||
|
||||
if(!_udp_ota.begin(_port)){
|
||||
log_e("udp bind failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!_hostname.length()) {
|
||||
char tmp[20];
|
||||
uint8_t mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
sprintf(tmp, "esp32-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
_hostname = tmp;
|
||||
}
|
||||
if(_mdnsEnabled){
|
||||
MDNS.begin(_hostname.c_str());
|
||||
MDNS.enableArduino(_port, (_password.length() > 0));
|
||||
}
|
||||
_initialized = true;
|
||||
_state = OTA_IDLE;
|
||||
log_i("OTA server at: %s.local:%u", _hostname.c_str(), _port);
|
||||
}
|
||||
|
||||
int ArduinoOTAClass::parseInt(){
|
||||
char data[INT_BUFFER_SIZE];
|
||||
uint8_t index = 0;
|
||||
char value;
|
||||
while(_udp_ota.peek() == ' ') _udp_ota.read();
|
||||
while(index < INT_BUFFER_SIZE - 1){
|
||||
value = _udp_ota.peek();
|
||||
if(value < '0' || value > '9'){
|
||||
data[index++] = '\0';
|
||||
return atoi(data);
|
||||
}
|
||||
data[index++] = _udp_ota.read();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String ArduinoOTAClass::readStringUntil(char end){
|
||||
String res = "";
|
||||
int value;
|
||||
while(true){
|
||||
value = _udp_ota.read();
|
||||
if(value <= 0 || value == end){
|
||||
return res;
|
||||
}
|
||||
res += (char)value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::_onRx(){
|
||||
if (_state == OTA_IDLE) {
|
||||
int cmd = parseInt();
|
||||
if (cmd != U_FLASH && cmd != U_SPIFFS)
|
||||
return;
|
||||
_cmd = cmd;
|
||||
_ota_port = parseInt();
|
||||
_size = parseInt();
|
||||
_udp_ota.read();
|
||||
_md5 = readStringUntil('\n');
|
||||
_md5.trim();
|
||||
if(_md5.length() != 32){
|
||||
log_e("bad md5 length");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_password.length()){
|
||||
MD5Builder nonce_md5;
|
||||
nonce_md5.begin();
|
||||
nonce_md5.add(String(micros()));
|
||||
nonce_md5.calculate();
|
||||
_nonce = nonce_md5.toString();
|
||||
|
||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||
_udp_ota.printf("AUTH %s", _nonce.c_str());
|
||||
_udp_ota.endPacket();
|
||||
_state = OTA_WAITAUTH;
|
||||
return;
|
||||
} else {
|
||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||
_udp_ota.print("OK");
|
||||
_udp_ota.endPacket();
|
||||
_ota_ip = _udp_ota.remoteIP();
|
||||
_state = OTA_RUNUPDATE;
|
||||
}
|
||||
} else if (_state == OTA_WAITAUTH) {
|
||||
int cmd = parseInt();
|
||||
if (cmd != U_AUTH) {
|
||||
log_e("%d was expected. got %d instead", U_AUTH, cmd);
|
||||
_state = OTA_IDLE;
|
||||
return;
|
||||
}
|
||||
_udp_ota.read();
|
||||
String cnonce = readStringUntil(' ');
|
||||
String response = readStringUntil('\n');
|
||||
if (cnonce.length() != 32 || response.length() != 32) {
|
||||
log_e("auth param fail");
|
||||
_state = OTA_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
String challenge = _password + ":" + String(_nonce) + ":" + cnonce;
|
||||
MD5Builder _challengemd5;
|
||||
_challengemd5.begin();
|
||||
_challengemd5.add(challenge);
|
||||
_challengemd5.calculate();
|
||||
String result = _challengemd5.toString();
|
||||
|
||||
if(result.equals(response)){
|
||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||
_udp_ota.print("OK");
|
||||
_udp_ota.endPacket();
|
||||
_ota_ip = _udp_ota.remoteIP();
|
||||
_state = OTA_RUNUPDATE;
|
||||
} else {
|
||||
_udp_ota.beginPacket(_udp_ota.remoteIP(), _udp_ota.remotePort());
|
||||
_udp_ota.print("Authentication Failed");
|
||||
log_w("Authentication Failed");
|
||||
_udp_ota.endPacket();
|
||||
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
|
||||
_state = OTA_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::_runUpdate() {
|
||||
const char *partition_label = _partition_label.length() ? _partition_label.c_str() : NULL;
|
||||
if (!Update.begin(_size, _cmd, -1, LOW, partition_label)) {
|
||||
|
||||
log_e("Begin ERROR: %s", Update.errorString());
|
||||
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_BEGIN_ERROR);
|
||||
}
|
||||
_state = OTA_IDLE;
|
||||
return;
|
||||
}
|
||||
Update.setMD5(_md5.c_str());
|
||||
|
||||
if (_start_callback) {
|
||||
_start_callback();
|
||||
}
|
||||
if (_progress_callback) {
|
||||
_progress_callback(0, _size);
|
||||
}
|
||||
|
||||
WiFiClient client;
|
||||
if (!client.connect(_ota_ip, _ota_port)) {
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_CONNECT_ERROR);
|
||||
}
|
||||
_state = OTA_IDLE;
|
||||
}
|
||||
|
||||
uint32_t written = 0, total = 0, tried = 0;
|
||||
|
||||
while (!Update.isFinished() && client.connected()) {
|
||||
size_t waited = _ota_timeout;
|
||||
size_t available = client.available();
|
||||
while (!available && waited){
|
||||
delay(1);
|
||||
waited -=1 ;
|
||||
available = client.available();
|
||||
}
|
||||
if (!waited){
|
||||
if(written && tried++ < 3){
|
||||
log_i("Try[%u]: %u", tried, written);
|
||||
if(!client.printf("%u", written)){
|
||||
log_e("failed to respond");
|
||||
_state = OTA_IDLE;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
log_e("Receive Failed");
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_RECEIVE_ERROR);
|
||||
}
|
||||
_state = OTA_IDLE;
|
||||
Update.abort();
|
||||
return;
|
||||
}
|
||||
if(!available){
|
||||
log_e("No Data: %u", waited);
|
||||
_state = OTA_IDLE;
|
||||
break;
|
||||
}
|
||||
tried = 0;
|
||||
static uint8_t buf[1460];
|
||||
if(available > 1460){
|
||||
available = 1460;
|
||||
}
|
||||
size_t r = client.read(buf, available);
|
||||
if(r != available){
|
||||
log_w("didn't read enough! %u != %u", r, available);
|
||||
}
|
||||
|
||||
written = Update.write(buf, r);
|
||||
if (written > 0) {
|
||||
if(written != r){
|
||||
log_w("didn't write enough! %u != %u", written, r);
|
||||
}
|
||||
if(!client.printf("%u", written)){
|
||||
log_w("failed to respond");
|
||||
}
|
||||
total += written;
|
||||
if(_progress_callback) {
|
||||
_progress_callback(total, _size);
|
||||
}
|
||||
} else {
|
||||
log_e("Write ERROR: %s", Update.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
if (Update.end()) {
|
||||
client.print("OK");
|
||||
client.stop();
|
||||
delay(10);
|
||||
if (_end_callback) {
|
||||
_end_callback();
|
||||
}
|
||||
if(_rebootOnSuccess){
|
||||
//let serial/network finish tasks that might be given in _end_callback
|
||||
delay(100);
|
||||
ESP.restart();
|
||||
}
|
||||
} else {
|
||||
if (_error_callback) {
|
||||
_error_callback(OTA_END_ERROR);
|
||||
}
|
||||
Update.printError(client);
|
||||
client.stop();
|
||||
delay(10);
|
||||
log_e("Update ERROR: %s", Update.errorString());
|
||||
_state = OTA_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::end() {
|
||||
_initialized = false;
|
||||
_udp_ota.stop();
|
||||
if(_mdnsEnabled){
|
||||
MDNS.end();
|
||||
}
|
||||
_state = OTA_IDLE;
|
||||
log_i("OTA server stopped.");
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::handle() {
|
||||
if (!_initialized) {
|
||||
return;
|
||||
}
|
||||
if (_state == OTA_RUNUPDATE) {
|
||||
_runUpdate();
|
||||
_state = OTA_IDLE;
|
||||
}
|
||||
if(_udp_ota.parsePacket()){
|
||||
_onRx();
|
||||
}
|
||||
_udp_ota.flush(); // always flush, even zero length packets must be flushed.
|
||||
}
|
||||
|
||||
int ArduinoOTAClass::getCommand() {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
void ArduinoOTAClass::setTimeout(int timeoutInMillis) {
|
||||
_ota_timeout = timeoutInMillis;
|
||||
}
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
||||
ArduinoOTAClass ArduinoOTA;
|
||||
#endif
|
116
libraries/ArduinoOTA/src/ArduinoOTA.h
Normal file
116
libraries/ArduinoOTA/src/ArduinoOTA.h
Normal file
@ -0,0 +1,116 @@
|
||||
#ifndef __ARDUINO_OTA_H
|
||||
#define __ARDUINO_OTA_H
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <functional>
|
||||
#include "Update.h"
|
||||
|
||||
#define INT_BUFFER_SIZE 16
|
||||
|
||||
typedef enum {
|
||||
OTA_IDLE,
|
||||
OTA_WAITAUTH,
|
||||
OTA_RUNUPDATE
|
||||
} ota_state_t;
|
||||
|
||||
typedef enum {
|
||||
OTA_AUTH_ERROR,
|
||||
OTA_BEGIN_ERROR,
|
||||
OTA_CONNECT_ERROR,
|
||||
OTA_RECEIVE_ERROR,
|
||||
OTA_END_ERROR
|
||||
} ota_error_t;
|
||||
|
||||
class ArduinoOTAClass
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(void)> THandlerFunction;
|
||||
typedef std::function<void(ota_error_t)> THandlerFunction_Error;
|
||||
typedef std::function<void(unsigned int, unsigned int)> THandlerFunction_Progress;
|
||||
|
||||
ArduinoOTAClass();
|
||||
~ArduinoOTAClass();
|
||||
|
||||
//Sets the service port. Default 3232
|
||||
ArduinoOTAClass& setPort(uint16_t port);
|
||||
|
||||
//Sets the device hostname. Default esp32-xxxxxx
|
||||
ArduinoOTAClass& setHostname(const char *hostname);
|
||||
String getHostname();
|
||||
|
||||
//Sets the password that will be required for OTA. Default NULL
|
||||
ArduinoOTAClass& setPassword(const char *password);
|
||||
|
||||
//Sets the password as above but in the form MD5(password). Default NULL
|
||||
ArduinoOTAClass& setPasswordHash(const char *password);
|
||||
|
||||
//Sets the partition label to write to when updating SPIFFS. Default NULL
|
||||
ArduinoOTAClass &setPartitionLabel(const char *partition_label);
|
||||
String getPartitionLabel();
|
||||
|
||||
//Sets if the device should be rebooted after successful update. Default true
|
||||
ArduinoOTAClass& setRebootOnSuccess(bool reboot);
|
||||
|
||||
//Sets if the device should advertise itself to Arduino IDE. Default true
|
||||
ArduinoOTAClass& setMdnsEnabled(bool enabled);
|
||||
|
||||
//This callback will be called when OTA connection has begun
|
||||
ArduinoOTAClass& onStart(THandlerFunction fn);
|
||||
|
||||
//This callback will be called when OTA has finished
|
||||
ArduinoOTAClass& onEnd(THandlerFunction fn);
|
||||
|
||||
//This callback will be called when OTA encountered Error
|
||||
ArduinoOTAClass& onError(THandlerFunction_Error fn);
|
||||
|
||||
//This callback will be called when OTA is receiving data
|
||||
ArduinoOTAClass& onProgress(THandlerFunction_Progress fn);
|
||||
|
||||
//Starts the ArduinoOTA service
|
||||
void begin();
|
||||
|
||||
//Ends the ArduinoOTA service
|
||||
void end();
|
||||
|
||||
//Call this in loop() to run the service
|
||||
void handle();
|
||||
|
||||
//Gets update command type after OTA has started. Either U_FLASH or U_SPIFFS
|
||||
int getCommand();
|
||||
|
||||
void setTimeout(int timeoutInMillis);
|
||||
|
||||
private:
|
||||
int _port;
|
||||
String _password;
|
||||
String _hostname;
|
||||
String _partition_label;
|
||||
String _nonce;
|
||||
WiFiUDP _udp_ota;
|
||||
bool _initialized;
|
||||
bool _rebootOnSuccess;
|
||||
bool _mdnsEnabled;
|
||||
ota_state_t _state;
|
||||
int _size;
|
||||
int _cmd;
|
||||
int _ota_port;
|
||||
int _ota_timeout;
|
||||
IPAddress _ota_ip;
|
||||
String _md5;
|
||||
|
||||
THandlerFunction _start_callback;
|
||||
THandlerFunction _end_callback;
|
||||
THandlerFunction_Error _error_callback;
|
||||
THandlerFunction_Progress _progress_callback;
|
||||
|
||||
void _runUpdate(void);
|
||||
void _onRx(void);
|
||||
int parseInt(void);
|
||||
String readStringUntil(char end);
|
||||
};
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_ARDUINOOTA)
|
||||
extern ArduinoOTAClass ArduinoOTA;
|
||||
#endif
|
||||
|
||||
#endif /* __ARDUINO_OTA_H */
|
Reference in New Issue
Block a user