Skip to content
Permalink
Browse files

Added OTA update

Both via web interface at settings and via Arduino IDE when connected to the same nentwork
  • Loading branch information...
spacehuhn committed Oct 18, 2019
1 parent e7f7632 commit a13739eab14974a0df8f61b6068509b1372b5b99
Showing with 119 additions and 16 deletions.
  1. +15 −0 README.md
  2. +2 −1 esp_duck/esp_duck.ino
  3. +10 −10 esp_duck/webfiles.h
  4. +77 −4 esp_duck/webserver.cpp
  5. +1 −0 esp_duck/webserver.h
  6. BIN img/ota.jpg
  7. +13 −0 web/settings.html
  8. +1 −1 web/style.css
@@ -39,6 +39,7 @@ Also available: <a href="https://www.tindie.com/products/Spacehuhn/spacehuhn-sti
- [Usage](#usage)
- [CLI](#cli)
- [Ducky Script](#ducky-script)
- [Debug](#debug)
- [FAQ](#faq)
- [Development](#development)
- [Edit Web Files](#edit-web-files)
@@ -285,6 +286,20 @@ ENTER
STRING Hello World!
```

### Debug

To properly debug, you need to have both the Atmega32u4
and the ESP82xx connected via USB to your computer.

That can be tricky when you only have a all in one board, so it might be useful
you built one yourself. You don't need to solder it, for example you can use an
Arduino Leonardo and a NodeMCU and connect them with jumper cables.

Now open 2 instances of Arduino (so they run as separate processes!),
select the COM port and open the serial monitor for each device.
You might need to reset the Atmega32u4 to see serial output.
If that causes problems with the i2c connection, try to reset the ESP82xx too.

### FAQ

If you have a question, you can check out the [issue section](../../issues).
@@ -34,11 +34,12 @@ void setup() {

webserver::begin();

debugln("\nESP Duck Started");
debugln("\nESP Duck Started!");
}

void loop() {
i2c::update();
webserver::update();

if (Serial.available()) {
String input = Serial.readStringUntil('\n');

Large diffs are not rendered by default.

@@ -7,9 +7,12 @@
#include "webserver.h"

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>


#include "config.h"
#include "debug.h"
#include "cli.h"
@@ -29,16 +32,19 @@ void reply(AsyncWebServerRequest* request, int code, const char* type, const uin

namespace webserver {
// ===== PRIVATE ===== //
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
AsyncEventSource events("/events");

const char* host_name = "wifiduck";

AsyncWebSocketClient* currentClient { nullptr };

bool reboot = false;

void wsEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
if (type == WS_EVT_CONNECT) {
debugf("WS Client connected %u\n", client->id());

// client->printf("%u", client->id());
}

else if (type == WS_EVT_DISCONNECT) {
@@ -83,6 +89,8 @@ namespace webserver {
// ===== PUBLIC ===== //
void begin() {
// Access Point
WiFi.hostname(host_name);
// WiFi.mode(WIFI_AP_STA);
WiFi.softAP(settings::getSSID(), settings::getPassword(), settings::getChannelNum());
debugf("Started Access Point \"%s\":\"%s\"\n", settings::getSSID(), settings::getPassword());

@@ -97,6 +105,66 @@ namespace webserver {

WEBSERVER_CALLBACK;

// Arduino OTA Update
ArduinoOTA.onStart([]() {
events.send("Update Start", "ota");
});
ArduinoOTA.onEnd([]() {
events.send("Update End", "ota");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
char p[32];
sprintf(p, "Progress: %u%%\n", (progress/(total/100)));
events.send(p, "ota");
});
ArduinoOTA.onError([](ota_error_t error) {
if (error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota");
else if (error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota");
else if (error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota");
else if (error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota");
else if (error == OTA_END_ERROR) events.send("End Failed", "ota");
});
ArduinoOTA.setHostname(host_name);
ArduinoOTA.begin();

events.onConnect([](AsyncEventSourceClient* client) {
client->send("hello!", NULL, millis(), 1000);
});
server.addHandler(&events);

// Web OTA
server.on("/update", HTTP_POST, [](AsyncWebServerRequest* request) {
reboot = !Update.hasError();

AsyncWebServerResponse* response;
response = request->beginResponse(200, "text/plain", reboot ? "OK" : "FAIL");
response->addHeader("Connection", "close");

request->send(response);
}, [](AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final) {
if (!index) {
Serial.printf("Update Start: %s\n", filename.c_str());
Update.runAsync(true);
if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)) {
Update.printError(Serial);
}
}
if (!Update.hasError()) {
if (Update.write(data, len) != len) {
Update.printError(Serial);
}
}
if (final) {
if (Update.end(true)) {
Serial.printf("Update Success: %uB\n", index+len);
} else {
Update.printError(Serial);
}
}
});

MDNS.addService("http", "tcp", 80);

// Websocket
ws.onEvent(wsEvent);
server.addHandler(&ws);
@@ -106,6 +174,11 @@ namespace webserver {
debugln("Started Webserver");
}

void update() {
ArduinoOTA.handle();
if (reboot) ESP.restart();
}

void send(const char* str) {
if (currentClient) currentClient->text(str);
}
@@ -8,5 +8,6 @@

namespace webserver {
void begin();
void update();
void send(const char* str);
}
BIN +43.1 KB img/ota.jpg
Binary file not shown.
@@ -58,6 +58,19 @@ <h2>WiFi</h2>

<p>Restart the device to apply new settings.</p>

<h2>Update</h2>

<p>
Go to <a href="https://github.com/spacehuhn/WiFiDuck/releases" target="_blank">wifiduck.com/releases</a>
to check for updates.<br>
Select a .bin file and press upload to flash the device.<br>
</p>

<form method='POST' action='/update' enctype='multipart/form-data'>
<input type='file' name='update'>
<input type='submit' class="warn" value='Upload'>
</form>

<footer>
<a href="settings.html">Settings</a> |
<a href="terminal.html">Terminal</a> |
@@ -376,7 +376,7 @@ input[type="text"] {
}

input[type="file"] {
display: none;
padding: 1em 0;
}

/* ==== GRID SYSTEM ==== */

0 comments on commit a13739e

Please sign in to comment.
You can’t perform that action at this time.