9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@@ -38,10 +38,11 @@ jobs:
|
||||
cmake -D CMAKE_TOOLCHAIN_FILE=../arduino-toolchain/Arduino-toolchain.cmake ..
|
||||
echo "# Espressif ESP32 Partition Table" > partitions.csv
|
||||
echo "# Name, Type, SubType, Offset, Size, Flags" >> partitions.csv
|
||||
echo "nvs,data,nvs,0x9000,20K," >> partitions.csv
|
||||
echo "otadata,data,ota,0xe000,8K," >> partitions.csv
|
||||
echo "app0,app,ota_0,0x10000,3M," >> partitions.csv
|
||||
echo "spiffs,data,spiffs,0x310000,960K," >> partitions.csv
|
||||
echo "nvs, data, nvs, 0x9000, 0x5000," >> partitions.csv
|
||||
echo "otadata, data, ota, 0xe000, 0x2000," >> partitions.csv
|
||||
echo "app0, app, ota_0, 0x10000, 0x1E0000," >> partitions.csv
|
||||
echo "app1, app, ota_1, 0x1F0000,0x1E0000," >> partitions.csv
|
||||
echo "spiffs, data, spiffs, 0x3D0000,0x30000," >> partitions.csv
|
||||
make
|
||||
- name: Upload artifacts
|
||||
run: |
|
||||
|
||||
@@ -37,6 +37,7 @@ file(GLOB SRCFILES
|
||||
NukiWrapper.cpp
|
||||
NukiOpenerWrapper.cpp
|
||||
MqttTopics.h
|
||||
Ota.cpp
|
||||
WebCfgServer.cpp
|
||||
PresenceDetection.cpp
|
||||
PreferencesKeys.h
|
||||
|
||||
29
Ota.cpp
Normal file
29
Ota.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <Arduino.h>
|
||||
#include "Ota.h"
|
||||
|
||||
#define FULL_PACKET 1436 // HTTP_UPLOAD_BUFLEN in WebServer,h
|
||||
|
||||
void Ota::updateFirmware(uint8_t* buf, size_t size)
|
||||
{
|
||||
if (!_updateFlag)
|
||||
{ //If it's the first packet of OTA since bootup, begin OTA
|
||||
Serial.println("BeginOTA");
|
||||
esp_ota_begin(esp_ota_get_next_update_partition(NULL), OTA_SIZE_UNKNOWN, &otaHandler);
|
||||
_updateFlag = true;
|
||||
}
|
||||
esp_ota_write(otaHandler, buf, size);
|
||||
if (size != FULL_PACKET)
|
||||
{
|
||||
esp_ota_end(otaHandler);
|
||||
Serial.println("EndOTA");
|
||||
if (ESP_OK == esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL)))
|
||||
{
|
||||
delay(2000);
|
||||
esp_restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Upload Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Ota.h
Normal file
15
Ota.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
#include "esp_ota_ops.h"
|
||||
|
||||
class Ota
|
||||
{
|
||||
public:
|
||||
void updateFirmware(uint8_t* buf, size_t size);
|
||||
|
||||
private:
|
||||
bool _updateFlag = false;
|
||||
esp_ota_handle_t otaHandler = 0;
|
||||
};
|
||||
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define nuki_hub_version "3.1"
|
||||
#define nuki_hub_version "4.0"
|
||||
@@ -112,6 +112,27 @@ void WebCfgServer::initialize()
|
||||
waitAndProcess(false, 1000);
|
||||
}
|
||||
});
|
||||
_server.on("/ota", [&]() {
|
||||
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
|
||||
return _server.requestAuthentication();
|
||||
}
|
||||
String response = "";
|
||||
buildOtaHtml(response);
|
||||
_server.send(200, "text/html", response);
|
||||
});
|
||||
_server.on("/uploadota", HTTP_POST, [&]() {
|
||||
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
|
||||
return _server.requestAuthentication();
|
||||
}
|
||||
|
||||
_server.send(200, "text/html", "");
|
||||
}, [&]() {
|
||||
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
|
||||
return _server.requestAuthentication();
|
||||
}
|
||||
|
||||
handleOtaUpload();
|
||||
});
|
||||
|
||||
_server.begin();
|
||||
}
|
||||
@@ -366,6 +387,11 @@ void WebCfgServer::buildHtml(String& response)
|
||||
response.concat("<button type=\"submit\">Edit</button>");
|
||||
response.concat("</form>");
|
||||
|
||||
response.concat("<BR><BR><h3>Firmware update</h3>");
|
||||
response.concat("<form method=\"get\" action=\"/ota\">");
|
||||
response.concat("<button type=\"submit\">Open</button>");
|
||||
response.concat("</form>");
|
||||
|
||||
if(_allowRestartToPortal)
|
||||
{
|
||||
response.concat("<br><br><h3>WiFi</h3>");
|
||||
@@ -438,14 +464,32 @@ void WebCfgServer::buildCredHtml(String &response)
|
||||
}
|
||||
|
||||
|
||||
response.concat("</BODY>\n");
|
||||
response.concat("</HTML>\n");
|
||||
}
|
||||
|
||||
void WebCfgServer::buildOtaHtml(String &response)
|
||||
{
|
||||
buildHtmlHeader(response);
|
||||
response.concat("<form id=\"upform\" enctype=\"multipart/form-data\" action=\"/uploadota\" method=\"POST\"><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"100000\" />Choose a file to upload: <input name=\"uploadedfile\" type=\"file\" accept=\".bin\" /><br/>");
|
||||
response.concat("<br><input id=\"submitbtn\" type=\"submit\" value=\"Upload File\" /></form>");
|
||||
response.concat("<div id=\"msgdiv\" style=\"visibility:hidden\">Initiating Over-the-air update. This will take about a minute, please be patient.<br>You will be forwarwed automatically when the update is complete.</div>");
|
||||
response.concat("<script type=\"text/javascript\">");
|
||||
response.concat("window.addEventListener('load', function () {");
|
||||
response.concat(" var button = document.getElementById(\"submitbtn\");");
|
||||
response.concat(" button.addEventListener('click',hideshow,false);");
|
||||
response.concat(" function hideshow() {");
|
||||
response.concat(" document.getElementById('upform').style.visibility = 'hidden';");
|
||||
response.concat(" document.getElementById('msgdiv').style.visibility = 'visible';");
|
||||
response.concat(" setTimeout(\"location.href = '/';\",60000);");
|
||||
response.concat(" }");
|
||||
response.concat("});");
|
||||
response.concat("</script>");
|
||||
response.concat("</BODY>\n</HTML>\n");
|
||||
}
|
||||
|
||||
void WebCfgServer::buildMqttConfigHtml(String &response)
|
||||
{
|
||||
response.concat("<FORM ACTION=method=get >");
|
||||
response.concat("<h3>MQTT COnfiguration</h3>");
|
||||
response.concat("<h3>MQTT Configuration</h3>");
|
||||
response.concat("<table>");
|
||||
printInputField(response, "HOSTNAME", "Host name", _preferences->getString(preference_hostname).c_str(), 100);
|
||||
printInputField(response, "MQTTSERVER", "MQTT Broker", _preferences->getString(preference_mqtt_broker).c_str(), 100);
|
||||
@@ -661,3 +705,28 @@ void WebCfgServer::waitAndProcess(const bool blocking, const uint32_t duration)
|
||||
}
|
||||
}
|
||||
|
||||
void WebCfgServer::handleOtaUpload()
|
||||
{
|
||||
if (_server.uri() != "/uploadota") {
|
||||
return;
|
||||
}
|
||||
|
||||
esp_task_wdt_init(30, false);
|
||||
|
||||
HTTPUpload& upload = _server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
String filename = upload.filename;
|
||||
if (!filename.startsWith("/")) {
|
||||
filename = "/" + filename;
|
||||
}
|
||||
Serial.print("handleFileUpload Name: "); Serial.println(filename);
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
_transferredSize = _transferredSize + upload.currentSize;
|
||||
Serial.println(_transferredSize);
|
||||
_ota.updateFirmware(upload.buf, upload.currentSize);
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
Serial.println();
|
||||
Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "NukiWrapper.h"
|
||||
#include "Network.h"
|
||||
#include "NukiOpenerWrapper.h"
|
||||
#include "Ota.h"
|
||||
|
||||
enum class TokenType
|
||||
{
|
||||
@@ -32,6 +33,7 @@ private:
|
||||
bool processArgs(String& message);
|
||||
void buildHtml(String& response);
|
||||
void buildCredHtml(String& response);
|
||||
void buildOtaHtml(String& response);
|
||||
void buildMqttConfigHtml(String& response);
|
||||
void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5);
|
||||
void buildConfigureWifiHtml(String& response);
|
||||
@@ -47,17 +49,21 @@ private:
|
||||
|
||||
String generateConfirmCode();
|
||||
void waitAndProcess(const bool blocking, const uint32_t duration);
|
||||
void handleOtaUpload();
|
||||
|
||||
WebServer _server;
|
||||
NukiWrapper* _nuki;
|
||||
NukiOpenerWrapper* _nukiOpener;
|
||||
Network* _network;
|
||||
Preferences* _preferences;
|
||||
Ota _ota;
|
||||
|
||||
bool _hasCredentials = false;
|
||||
char _credUser[20] = {0};
|
||||
char _credPassword[20] = {0};
|
||||
bool _allowRestartToPortal = false;
|
||||
uint32_t _transferredSize = 0;
|
||||
bool _otaStart = true;
|
||||
|
||||
String _confirmCode = "----";
|
||||
|
||||
|
||||
2
main.cpp
2
main.cpp
@@ -89,7 +89,7 @@ void setupTasks()
|
||||
{
|
||||
// configMAX_PRIORITIES is 25
|
||||
|
||||
xTaskCreate(networkTask, "ntw", 8192, NULL, 3, NULL);
|
||||
xTaskCreatePinnedToCore(networkTask, "ntw", 8192, NULL, 3, NULL, 1);
|
||||
xTaskCreate(nukiTask, "nuki", 4096, NULL, 2, NULL);
|
||||
xTaskCreate(presenceDetectionTask, "prdet", 768, NULL, 5, NULL);
|
||||
xTaskCreate(checkMillisTask, "mlchk", 512, NULL, 1, NULL);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user