From a3beaa664a1717336ef55c413df0367e855af644 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Date: Mon, 12 Oct 2015 10:25:16 +0200 Subject: [PATCH] OTA support encapsulated to ArduinoOTA class --- .../libraries/ArduinoOTA/ArduinoOTA.cpp | 113 ++++++++++++++++++ .../esp8266/libraries/ArduinoOTA/ArduinoOTA.h | 35 ++++++ .../ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 31 +++++ .../ArduinoOTA/examples/OTALeds/OTALeds.ino | 71 +++++++++++ .../esp8266/libraries/ArduinoOTA/keywords.txt | 26 ++++ .../libraries/ArduinoOTA/library.properties | 9 ++ 6 files changed, 285 insertions(+) create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.cpp create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.h create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/keywords.txt create mode 100644 hardware/esp8266com/esp8266/libraries/ArduinoOTA/library.properties diff --git a/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.cpp b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.cpp new file mode 100644 index 0000000000..82b4d14113 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include "ArduinoOTA.h" + +ArduinoOTA::ArduinoOTA(const char *mdns_host_prefix, int port, bool serial_debug) +{ + _port = port; + _mdns_host = new String(mdns_host_prefix); + *_mdns_host += String(ESP.getChipId(), HEX); + _udp_ota = new WiFiUDP(); + _serial_debug = serial_debug; + + _start_callback = NULL; + _end_callback = NULL; + _progress_callback = NULL; + _error_callback = NULL; +} + +void ArduinoOTA::onStart(OTA_CALLBACK(fn)){ + _start_callback = fn; +} + +void ArduinoOTA::onEnd(OTA_CALLBACK(fn)){ + _end_callback = fn; +} + +void ArduinoOTA::onProgress(OTA_CALLBACK_PROGRESS(fn)){ + _progress_callback = fn; +} + +void ArduinoOTA::onError(OTA_CALLBACK(fn)){ + _error_callback = fn; +} + +ArduinoOTA::~ArduinoOTA(){ + delete _udp_ota; + delete _mdns_host; +} + +void ArduinoOTA::setup() { + _udp_ota->begin(_port); + if (_mdns_host) { + if (_serial_debug) + Serial.printf("OTA server at: %s:%u\n", + _mdns_host->c_str(), + _port); + MDNS.begin(_mdns_host->c_str()); + MDNS.addService("arduino", "tcp", _port); + } +} + +void ArduinoOTA::handle() { + + if (!_udp_ota->parsePacket()) return; + + IPAddress remote = _udp_ota->remoteIP(); + int cmd = _udp_ota->parseInt(); + int port = _udp_ota->parseInt(); + int size = _udp_ota->parseInt(); + + if (_serial_debug){ + Serial.print("Update Start: ip:"); + Serial.print(remote); + Serial.printf(", port:%d, size:%d\n", port, size); + } + + WiFiUDP::stopAll(); + + if(!Update.begin(size)){ + if (_serial_debug) + Serial.println("Update Begin Error"); + if (_error_callback) _error_callback(); + _udp_ota->begin(_port); + return; + } + if (_start_callback) _start_callback(); + if (_progress_callback) _progress_callback(0, size); + + WiFiClient client; + if (!client.connect(remote, port)) { + if (_serial_debug) + Serial.printf("Connect Failed\n"); + _udp_ota->begin(_port); + if (_error_callback) _error_callback(); + } + + uint32_t written; + while(!Update.isFinished() && client.connected()){ + // TODO(mangelajo): enhance the Update.write(client) to + // accept a progress callback + written = Update.write(client); + if(written > 0) client.print(written, DEC); + if(_progress_callback) _progress_callback(written, size); + } + + Serial.setDebugOutput(false); + + if(Update.end()){ + client.println("OK"); + if (_serial_debug) + Serial.printf("Update Success\nRebooting...\n"); + if(_end_callback) _end_callback(); + ESP.restart(); + } else { + // Update failed: listen UDP again, callback and print + _udp_ota->begin(_port); + if (_error_callback) _error_callback(); + Update.printError(client); + if (_serial_debug) + Update.printError(Serial); + } +} diff --git a/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.h b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.h new file mode 100644 index 0000000000..1413306e8c --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/ArduinoOTA.h @@ -0,0 +1,35 @@ +#ifndef __ARDUINO_OTA_H +#define __ARDUINO_OTA_H + +class WiFiUDP; + +#define OTA_CALLBACK(callback) void (*callback)() +#define OTA_CALLBACK_PROGRESS(callback) void (*callback)(unsigned int, unsigned int) + +class ArduinoOTA +{ + int _port; + String* _mdns_host; + WiFiUDP* _udp_ota; + bool _serial_debug; + + OTA_CALLBACK(_start_callback); + OTA_CALLBACK(_end_callback); + OTA_CALLBACK(_error_callback); + + OTA_CALLBACK_PROGRESS(_progress_callback); + + public: + ArduinoOTA(const char *mdns_host="ESP8266-OTA-", + int port=8266, + bool serial_debug=true); + ~ArduinoOTA(); + void setup(); + void handle(); + void onStart(OTA_CALLBACK(fn)); + void onEnd(OTA_CALLBACK(fn)); + void onProgress(OTA_CALLBACK_PROGRESS(fn)); + void onError(OTA_CALLBACK (fn)); +}; + +#endif /* __ARDUINO_OTA_H */ diff --git a/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino new file mode 100644 index 0000000000..0f8967f898 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +const char* ssid = "..."; +const char* password = "..."; + +ArduinoOTA ota_server; + +void setup() { + Serial.begin(115200); + + Serial.println("Booting"); + WiFi.mode(WIFI_STA); + + /* try the flash stored password first */ + WiFi.begin(); + + while (WiFi.waitForConnectResult() != WL_CONNECTED){ + WiFi.begin(ssid, password); + Serial.println("Retrying connection..."); + } + ota_server.setup(); + Serial.println("Ready"); +} + +void loop() { + ota_server.handle(); + yield(); +} diff --git a/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino new file mode 100644 index 0000000000..208e0be084 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +const char* ssid = "..."; +const char* password = "..."; +const char* host_prefix = "OTA-LEDS-"; + +ArduinoOTA ota_server(host_prefix, 8266, /* debug_serial= */ true); + +int led_pin = 13; +#define N_DIMMERS 3 +int dimmer_pin[] = {14, 5, 15}; + +void setup() { + Serial.begin(115200); + + /* switch on led */ + pinMode(led_pin, OUTPUT); + digitalWrite(led_pin, LOW); + + Serial.println("Booting"); + WiFi.mode(WIFI_STA); + + /* try the flash stored password first */ + WiFi.begin(); + + while (WiFi.waitForConnectResult() != WL_CONNECTED){ + WiFi.begin(ssid, password); + Serial.println("Retrying connection..."); + } + /* switch off led */ + digitalWrite(led_pin, HIGH); + + /* setup the OTA server */ + ota_server.setup(); + Serial.println("Ready"); + + /* configure dimmers, and OTA server events */ + analogWriteRange(1000); + analogWrite(led_pin,990); + + for (int i=0; i +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=esp8266