eduperez wrote:Can an Arduino-based ESP device auto-update itself over-the-air?
I would like that as well. I've posted the OTA sketch below as included in the Arduino IDE example, but I've modified it so that the OTA 'listener' is a function that can be called at any point in the program.
So far, this has worked for me. I would much prefer if the ESP could update itself, though.
So we need to see how the ESP can connect to a publicly visible server and query the contents, and then I assume the 'OTA listener' can be modified to 'pull' the updated firmware and update itself (I hope).
EDIT: If you look under Examples -> ESP8266WebServer -> WebUpdate, this shows the ESP8266 hosting a small webpage where you can upload a freshly compiled firmware and it will update itself. Not exactly what we want, but it's a start. I have successfully tested it. Hopefully it works for you as well.
OTA Update sketch (slight modification of Arduino-included example)
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
/////////// STATIC IP CONFIGURATION ///////////
// Configure this for your preferences
// Comment this section out if using DHCP
IPAddress ip(192, 168, 1, 4);
IPAddress dns(8, 8, 8, 8);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
///////////////////////////////////////////////
const char* host = "esp8266-ota";
const char* ssid = "............";
const char* pass = "............";
const uint16_t aport = 8266;
WiFiServer TelnetServer(aport);
WiFiClient Telnet;
WiFiUDP OTA;
void setup() {
Serial.begin(115200);
Serial.print("\r\nArduino OTA Test\r\n");
Serial.printf("Sketch size: %u\r\n", ESP.getSketchSize());
Serial.printf("Free size: %u\r\n", ESP.getFreeSketchSpace());
WiFi.config(ip, dns, gateway, subnet); // Comment out this line if using DHCP
WiFi.begin(ssid, pass);
if(WiFi.waitForConnectResult() == WL_CONNECTED){
MDNS.begin(host);
MDNS.addService("arduino", "tcp", aport);
OTA.begin(aport);
TelnetServer.begin();
TelnetServer.setNoDelay(true);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
}
void loop() {
CheckOTAUpdate();
}
void CheckOTAUpdate(){
if (OTA.parsePacket()) {
IPAddress remote = OTA.remoteIP();
int cmd = OTA.parseInt();
int port = OTA.parseInt();
int size = OTA.parseInt();
Serial.print("\r\nUpdate Start: ip:");
Serial.print(remote);
Serial.printf(", port:%d, size:%d bytes\r\n", port, size);
uint32_t startTime = millis();
WiFiUDP::stopAll();
if(!Update.begin(size)){
Serial.print("Update Begin Error\r\n");
return;
}
WiFiClient client;
if (client.connect(remote, port)) {
uint32_t written;
while(!Update.isFinished()){
written = Update.write(client);
if(written > 0) client.print(written, DEC);
}
Serial.setDebugOutput(false);
if(Update.end()){
client.print("OK\r\n");
Serial.printf("Update Success: %u ms\r\nRebooting...\r\n", millis() - startTime);
ESP.restart();
} else {
Update.printError(client);
Update.printError(Serial);
}
} else {
Serial.printf("Connect Failed: %u ms\r\n", millis() - startTime);
}
}
if (TelnetServer.hasClient()){
if (!Telnet || !Telnet.connected()){
if(Telnet) Telnet.stop();
Telnet = TelnetServer.available();
} else {
WiFiClient toKill = TelnetServer.available();
toKill.stop();
}
}
if (Telnet && Telnet.connected() && Telnet.available()){
while(Telnet.available())
Serial.write(Telnet.read());
}
if(Serial.available()){
size_t len = Serial.available();
uint8_t * sbuf = (uint8_t *)malloc(len);
Serial.readBytes(sbuf, len);
if (Telnet && Telnet.connected()){
Telnet.write((uint8_t *)sbuf, len);
yield();
}
free(sbuf);
}
delay(1);
}