Improve initial setup proc (#1692)

* Initial Test

* Initial functional version.
This commit is contained in:
jomjol
2022-12-27 10:20:55 +01:00
committed by GitHub
parent de223f51f6
commit 85030e39fa
12 changed files with 674 additions and 15 deletions

View File

@@ -895,7 +895,7 @@ void delete_all_in_directory(std::string _directory)
closedir(dir);
}
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main)
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main, bool _initial_setup)
{
int i, sort_iter;
mz_bool status;
@@ -905,13 +905,9 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
char archive_filename[64];
std::string zw, ret = "";
std::string directory = "";
// static const char* s_Test_archive_filename = "testhtml.zip";
ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION);
ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
// ESP_LOGD(TAG, "Target Dir ZIP: %s", _target_zip.c_str());
// ESP_LOGD(TAG, "Target Dir BIN: %s", _target_bin.c_str());
// ESP_LOGD(TAG, "Target Dir main: %s", _main.c_str());
// Now try to open the archive.
memset(&zip_archive, 0, sizeof(zip_archive));
@@ -928,7 +924,6 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
sort_iter = 0;
// for (sort_iter = 0; sort_iter < 2; sort_iter++)
{
memset(&zip_archive, 0, sizeof(zip_archive));
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
@@ -966,6 +961,16 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
else
{
std::string _dir = getDirectory(zw);
if ((_dir == "config-initial") && !_initial_setup)
{
continue;
}
else
{
_dir = "config";
std::string _s1 = "config-initial";
FindReplace(zw, _s1, _dir);
}
if (_dir.length() > 0)
{
@@ -1006,9 +1011,6 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
isokay = isokay && RenameFile(filename_zw, zw);
if (!isokay)
ESP_LOGE(TAG, "ERROR in Rename \"%s\" to \"%s\"", filename_zw.c_str(), zw.c_str());
// isokay = isokay && DeleteFile(filename_zw);
// if (!isokay)
// ESP_LOGE(TAG, "ERROR in Delete \"%s\"", filename_zw.c_str());
if (isokay)
ESP_LOGI(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);

View File

@@ -9,7 +9,7 @@
void register_server_file_uri(httpd_handle_t server, const char *base_path);
void unzip(std::string _in_zip_file, std::string _target_directory);
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/");
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/", bool _initial_setup = false);
void delete_all_in_directory(std::string _directory);

View File

@@ -48,7 +48,7 @@ esp_err_t handler_reboot(httpd_req_t *req);
static bool ota_update_task(std::string fn);
std::string _file_name_update;
bool initial_setup = false;
static void infinite_loop(void)
@@ -76,7 +76,7 @@ void task_do_Update_ZIP(void *pvParameter)
out = "/sdcard/html";
outbin = "/sdcard/firmware";
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/");
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/", "/sdcard/", initial_setup);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Files unzipped.");
if (retfirmware.length() > 0)
@@ -84,6 +84,12 @@ void task_do_Update_ZIP(void *pvParameter)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Found firmware.bin");
ota_update_task(retfirmware);
}
if (initial_setup)
{
}
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
doReboot();
}
@@ -106,6 +112,15 @@ void CheckUpdate()
char zw[1024] = "";
fgets(zw, 1024, pfile);
_file_name_update = std::string(zw);
if (fgets(zw, 1024, pfile))
{
std::string _szw = std::string(zw);
if (_szw == "init")
{
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Inital Setup triggered.");
initial_setup = true; }
}
fclose(pfile);
DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update during boot triggered - Update File: " + _file_name_update);

View File

@@ -301,6 +301,17 @@ bool RenameFile(string from, string to)
return true;
}
bool FileExists(string filename)
{
FILE* fpSourceFile = fopen(filename.c_str(), "rb");
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
{
return false;
}
fclose(fpSourceFile);
return true;
}
bool DeleteFile(string fn)
{
@@ -582,6 +593,17 @@ std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
}
std::string ReplaceString(std::string subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
/* SD Card Manufacturer Database */
struct SDCard_Manufacturer_database {

View File

@@ -18,6 +18,7 @@ bool CopyFile(string input, string output);
bool DeleteFile(string fn);
bool RenameFile(string from, string to);
bool MakeDir(std::string _what);
bool FileExists(string filename);
string RundeOutput(double _in, int _anzNachkomma);
@@ -31,6 +32,7 @@ string getFileType(string filename);
string getFileFullFileName(string filename);
string getDirectory(string filename);
int mkdir_r(const char *dir, const mode_t mode);
int removeFolder(const char* folderPath, const char* logTag);

View File

@@ -41,7 +41,7 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold)
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold)
{
std::string ssid = "";
std::string passphrase = "";
@@ -59,10 +59,13 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
fn = FormatFileName(fn);
pFile = fopen(fn.c_str(), "r");
if (!pFile)
return false;
ESP_LOGD(TAG, "file loaded");
if (pFile == NULL)
return;
return false;
char zw[1024];
fgets(zw, 1024, pFile);
@@ -193,6 +196,7 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
_rssithreashold = rssithreshold;
RSSIThreashold = rssithreshold;
return true;
}

View File

@@ -5,7 +5,7 @@
#include <string>
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold);
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold);
bool ChangeHostName(std::string fn, std::string _newhostname);
bool ChangeRSSIThreashold(std::string fn, int _newrssithreashold);

View File

@@ -39,6 +39,8 @@
#include "../../include/defines.h"
//#include "server_GPIO.h"
#include "softAP.h"
extern const char* GIT_TAG;
extern const char* GIT_REV;
extern const char* GIT_BRANCH;
@@ -175,6 +177,8 @@ extern "C" void app_main(void)
CheckOTAUpdate();
CheckUpdate();
CheckStartAPMode(); // if no wlan.ini and/or config.ini --> AP ist startet and this function does not exit anymore until reboot
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL; int rssithreashold = 0;
LoadWlanFromFile("/sdcard/wlan.ini", ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreashold);
@@ -318,3 +322,4 @@ extern "C" void app_main(void)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Not starting flows!");
}
}

View File

@@ -16,6 +16,8 @@
#include "server_tflite.h"
#include "esp_log.h"
#include <stdio.h>
#include "Helper.h"
httpd_handle_t server = NULL;
@@ -350,6 +352,7 @@ esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
esp_err_t sysinfo_handler(httpd_req_t *req)
{
const char* resp_str;
@@ -421,6 +424,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_register_uri_handler(server, &starttime_tmp_handle);
httpd_uri_t img_tmp_handle = {
.uri = "/img_tmp/*", // Match all URIs of type /path/to/file
.method = HTTP_GET,

489
code/main/softAP.cpp Normal file
View File

@@ -0,0 +1,489 @@
#include "softAP.h"
/* WiFi softAP Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <string>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "stdio.h"
#include "ClassLogFile.h"
#include "server_help.h"
#include "defines.h"
#include "Helper.h"
#include "server_ota.h"
#include "lwip/err.h"
#include "lwip/sys.h"
/* The examples use WiFi configuration that you can set via project configuration menu.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID "AI-on-the-Edge"
#define EXAMPLE_ESP_WIFI_PASS ""
#define EXAMPLE_ESP_WIFI_CHANNEL 11
#define EXAMPLE_MAX_STA_CONN 1
bool isConfigINI = false;
bool isWlanINI = false;
static const char *TAG = "wifi softAP";
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
void wifi_init_softAP(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = { };
strcpy((char*)wifi_config.ap.ssid, (const char*) EXAMPLE_ESP_WIFI_SSID);
strcpy((char*)wifi_config.ap.password, (const char*) EXAMPLE_ESP_WIFI_PASS);
wifi_config.ap.channel = EXAMPLE_ESP_WIFI_CHANNEL;
wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
void SendHTTPResponse(httpd_req_t *req)
{
std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
message += "This mode is always startet if one of the following files is missing: /wlan.ini or the /config/config.ini.<p>";
message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN acces information, 3. reboot (and connect to WLANs)<p><p>";
message += "Please follow the below instructions.<p>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
isWlanINI = FileExists("/sdcard/wlan.ini");
if (!isConfigINI)
{
message = "<h3>1. Upload initial configuration to sd-card</h3><p>";
message += "The configuration file config.ini is missing and most propably the full configuration and html folder on the sd-card. ";
message += "This is normal after the first flashing of the firmware and an empty sd-card. Please upload \"remote_setup.zip\", which contains an full inital configuration.<p>";
message += "<input id=\"newfile\" type=\"file\">";
message += "<button class=\"button\" style=\"width:300px\" id=\"doUpdate\" type=\"button\" onclick=\"upload()\">Upload File</button><p>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
message = "<script language=\"JavaScript\">";
message += "function upload() {";
message += "var xhttp = new XMLHttpRequest();";
message += "xhttp.onreadystatechange = function() {if (xhttp.readyState == 4) {if (xhttp.status == 200) {location.reload();}}};";
message += "var filePath = document.getElementById(\"newfile\").value.split(/[\\\\/]/).pop();";
message += "var file = document.getElementById(\"newfile\").files[0];";
message += "if (!file.name.includes(\"remote-setup\")){if (!confirm(\"The zip file name should contain '...remote-setup...'. Are you sure that you have downloaded the correct file?\"))return;};";
message += "var upload_path = \"/upload/firmware/\" + filePath; xhttp.open(\"POST\", upload_path, true); xhttp.send(file);document.reload();}";
message += "</script>";
isConfigINI = true;
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
return;
}
if (!isWlanINI)
{
message = "<h3>2. WLAN access credentials</h3><p>";
message = "<table>";
message += "<tr><td>WLAN-SSID</td><td><input type=\"text\" name=\"ssid\" id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
message += "<tr><td>WLAN-Password</td><td><input type=\"text\" name=\"password\" id=\"password\"></td><td>ATTENTION: the password will not be encrypted during the sending.</td>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
// message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
// message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router</td></tr>";
// message += "<tr><td>gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router</td></tr>";
// message += "<tr><td>netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router</td>";
// message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router</td></tr>";
// message += "<tr><td>RSSI Threashold</td><td><input type=\"number\" name=\"name\" id=\"threashold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threashold for RSSI value to check for start switching access point in a mesh system.Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
// httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
message = "/<table><p>";
message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reset afterwards. If ssid or password is wrong, you need to take out the sd-card and manually change them in \"wlan.ini\"!<p>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
message += "<script language=\"JavaScript\">async function wr(){";
message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
// message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssi=\"+document.getElementById(\"threashold\").value;";
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
return;
}
message = "<h3>3. Reboot</h3><p>";
message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
message += "The first update and initialization process can take up to 3 minutes before you find it in the wlan. Errors can be found on the console / serial logout.<p>Have fun!<p>";
message += "<button class=\"button\" type=\"button\" onclick=\"rb()\")>Reboot to first setup.</button>";
message += "<script language=\"JavaScript\">async function rb(){";
message += "api = \"/reboot\";";
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
}
esp_err_t test_handler(httpd_req_t *req)
{
SendHTTPResponse(req);
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
esp_err_t reboot_handlerAP(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_ota_update - Start");
#endif
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
doReboot();
return ESP_OK;
};
esp_err_t config_ini_handler(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_ota_update - Start");
#endif
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "config_ini_handler");
char _query[400];
char _valuechar[100];
std::string fn = "/sdcard/firmware/";
std::string _task = "";
std::string ssid = "";
std::string pwd = "";
std::string hn = ""; // hostname
std::string ip = "";
std::string gw = ""; // gateway
std::string nm = ""; // nm
std::string dns = "";
std::string rssi = "";
if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
{
ESP_LOGD(TAG, "Query: %s", _query);
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
ssid = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "pwd", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "pwd is found: %s", _valuechar);
pwd = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
ssid = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "hn", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "hostname is found: %s", _valuechar);
hn = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "ip", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "ip is found: %s", _valuechar);
ip = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "gw", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "gateway is found: %s", _valuechar);
gw = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "nm", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "netmask is found: %s", _valuechar);
nm = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "dns", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "dns is found: %s", _valuechar);
dns = std::string(_valuechar);
}
if (httpd_query_key_value(_query, "rssi", _valuechar, 30) == ESP_OK)
{
ESP_LOGD(TAG, "rssi is found: %s", _valuechar);
rssi = std::string(_valuechar);
}
};
FILE* configfilehandle = fopen("/sdcard/wlan.ini", "w");
if (ssid.length())
ssid = "ssid = \"" + ssid + "\"\n";
else
ssid = ";ssid = \"\"\n";
fputs(ssid.c_str(), configfilehandle);
if (pwd.length())
pwd = "password = \"" + pwd + "\"\n";
else
pwd = ";password = \"\"\n";
fputs(pwd.c_str(), configfilehandle);
if (hn.length())
hn = "hostname = \"" + hn + "\"\n";
else
hn = ";hostname = \"\"\n";
fputs(hn.c_str(), configfilehandle);
if (ip.length())
ip = "ip = \"" + ip + "\"\n";
else
ip = ";ip = \"\"\n";
fputs(ip.c_str(), configfilehandle);
if (gw.length())
gw = "gateway = \"" + gw + "\"\n";
else
gw = ";gateway = \"\"\n";
fputs(gw.c_str(), configfilehandle);
if (nm.length())
nm = "netmask = \"" + nm + "\"\n";
else
nm = ";netmask = \"\"\n";
fputs(nm.c_str(), configfilehandle);
if (dns.length())
dns = "dns = \"" + dns + "\"\n";
else
dns = ";dns = \"\"\n";
fputs(dns.c_str(), configfilehandle);
if (rssi.length())
rssi = "RSSIThreashold = \"" + rssi + "\"\n";
else
rssi = ";rssi = \"\"\n";
fputs(rssi.c_str(), configfilehandle);
fflush(configfilehandle);
fclose(configfilehandle);
std::string zw = "ota without parameter - should not be the case!";
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGE(TAG, "end config.ini");
return ESP_OK;
};
esp_err_t upload_post_handlerAP(httpd_req_t *req)
{
printf("Start des Post Handlers\n");
MakeDir("/sdcard/config");
MakeDir("/sdcard/firmware");
MakeDir("/sdcard/html");
MakeDir("/sdcard/img_tmp");
MakeDir("/sdcard/log");
printf("Nach Start des Post Handlers\n");
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handlerAP");
char filepath[FILE_PATH_MAX];
FILE *fd = NULL;
const char *filename = get_path_from_uri(filepath, "/sdcard",
req->uri + sizeof("/upload") - 1, sizeof(filepath));
if (!filename) {
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
return ESP_FAIL;
}
printf("filepath: %s, filename: %s\n", filepath, filename);
DeleteFile(std::string(filepath));
fd = fopen(filepath, "w");
if (!fd) {
ESP_LOGE(TAG, "Failed to create file: %s", filepath);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Receiving file: %s...", filename);
char buf[1024];
int received;
int remaining = req->content_len;
printf("remaining: %d\n", remaining);
while (remaining > 0) {
ESP_LOGI(TAG, "Remaining size: %d", remaining);
if ((received = httpd_req_recv(req, buf, MIN(remaining, 1024))) <= 0) {
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
continue;
}
fclose(fd);
unlink(filepath);
ESP_LOGE(TAG, "File reception failed!");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
return ESP_FAIL;
}
if (received && (received != fwrite(buf, 1, received, fd))) {
fclose(fd);
unlink(filepath);
ESP_LOGE(TAG, "File write failed!");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
return ESP_FAIL;
}
remaining -= received;
}
FILE* pfile = fopen("/sdcard/update.txt", "w");
std::string _s_zw= "/sdcard" + std::string(filename);
fwrite(_s_zw.c_str(), strlen(_s_zw.c_str()), 1, pfile);
fclose(pfile);
fclose(fd);
ESP_LOGI(TAG, "File reception complete");
httpd_resp_set_hdr(req, "Location", "/test");
httpd_resp_set_status(req, "303 See Other");
httpd_resp_set_hdr(req, "Location", "/test");
// httpd_resp_sendstr(req, "File uploaded successfully");
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGI(TAG, "Update page send out");
// httpd_resp_sendstr(req, "File uploaded successfully");
return ESP_OK;
}
httpd_handle_t start_webserverAP(void)
{
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_wildcard;
httpd_handle_t server = NULL;
if (httpd_start(&server, &config) == ESP_OK) {
// Do something
}
httpd_uri_t reboot_handle = {
.uri = "/reboot", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = reboot_handlerAP,
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &reboot_handle);
httpd_uri_t config_ini_handle = {
.uri = "/config", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = config_ini_handler,
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &config_ini_handle);
/* URI handler for uploading files to server */
httpd_uri_t file_uploadAP = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handlerAP,
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &file_uploadAP);
httpd_uri_t test_uri = {
.uri = "*",
.method = HTTP_GET,
.handler = test_handler,
.user_ctx = NULL
};
httpd_register_uri_handler(server, &test_uri);
return NULL;
}
void CheckStartAPMode()
{
isConfigINI = FileExists("/sdcard/config/config.ini");
isWlanINI = FileExists("/sdcard/wlan.ini");
if (!isConfigINI or !isWlanINI)
{
wifi_init_softAP();
start_webserverAP();
while(1) { // wait until reboot within task_do_Update_ZIP
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
}

19
code/main/softAP.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef SOFTAP_H
#define SOFTAP_H
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_eth.h"
#include "protocol_examples_common.h"
#include "esp_tls_crypto.h"
#include <esp_http_server.h>
void CheckStartAPMode();
#endif

View File

@@ -0,0 +1,97 @@
<table>
<tr><td>WLAN-SSID</td><td><input type="text" name="ssid" id="ssid"></td><td>SSID of the WLAN</td></tr>
<tr><td>WLAN-Password</td><td><input type="text" name="password" id="password"></td><td>ATTENTION: the password will not be encrypted during the sending.</td>
</tr><tr><td> Hostname</td><td><input type="text" name="hostname" id="hostname"></td><td></td>
</tr><tr><td>Fixed IP</td><td><input type="text" name="ip" id="ip"></td><td>Leave emtpy if set by router</td></tr>
<tr><td>gateway</td><td><input type="text" name="gateway" id="gateway"></td><td>Leave emtpy if set by router</td></tr>
<tr><td>netmask</td><td><input type="text" name="netmask" id="netmask"></td><td>Leave emtpy if set by router</td>
</tr><tr><td>DNS</td><td><input type="text" name="dns" id="dns"></td><td>Leave emtpy if set by router</td></tr>
<tr><td>RSSI Threashold</td><td><input type="number" name="name" id="threashold" min="-100" max="0" step="1" value = "0"></td><td>WLAN Mesh Parameter: Threashold for RSSI value to check for start switching access point in a mesh system.Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>
</table>
<button class="button" type="button" onclick="wr()">Write wlan.ini</button>
<input id="newfile" type="file">
<button class="button" style="width:300px" id="doUpdate" type="button" onclick="upload()">Upload Files</button>
<script language="JavaScript">function wr(){
api = "/config?"+"ssid"+document.getElementById("ssid").value+"&pwd="+document.getElementById("password").value;+"&hn="+document.getElementById("hostname").value;+"&ip="+document.getElementById("ip").value;+"&gw="+document.getElementById("gateway").value;+"&nm="+document.getElementById("netmask").value;+"&dns="+document.getElementById("dns").value;+"&rssi="+document.getElementById("threashold").value;
fetch(api);}
function upload() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {stopProgressTimer();if (xhttp.status == 200) {extract();} }};
var filePath = document.getElementById("newfile").value.split(/[\\\/]/).pop();
var file = document.getElementById("newfile").files[0];
if (!file.name.includes("remote-setup"))
{
if (!confirm("The zip file name should contain \"...remote-setup...\". Are you sure that you have downloaded the correct file?"))
return;
}
var upload_path = "/upload/firmware/" + filePath; xhttp.open("POST", upload_path, true); xhttp.send(file);}
function extract() {
document.getElementById("status").innerText = "Status: Processing on device (takes up to 3 minutes)...";
var xhttp = new XMLHttpRequest();
/* first delete the old firmware */
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
stopProgressTimer();
if (xhttp.status == 200) {
document.getElementById("status").innerText = "Status: Update completed!";
document.getElementById("doUpdate").disabled = true;
document.getElementById("newfile").disabled = false;
document.cookie = "page=overview.html"; // Make sure after the reboot we go to the overview page
if (xhttp.responseText.startsWith("reboot"))
{
doRebootAfterUpdate();
}
else
{
alert("Processing done!\n\n" + xhttp.responseText);
}
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
UpdatePage();
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
UpdatePage();
}
}
};
startProgressTimer("Extraction");
var nameneu = document.getElementById("newfile").value;
filePath = nameneu.split(/[\\\/]/).pop();
var _toDo = basepath + "/ota?task=update&file=" + filePath;
xhttp.open("GET", _toDo, true);
xhttp.send();
}
function startProgressTimer(step) {
console.log(step + "...");
document.getElementById('progress').innerHTML = "(0s)";
action_runtime = 0;
progressTimerHandle = setInterval(function() {
action_runtime += 1;
console.log("Progress: " + action_runtime + "s");
document.getElementById('progress').innerHTML = "(" + action_runtime + "s)";
}, 1000);
}
function stopProgressTimer() {
clearInterval(progressTimerHandle);
document.getElementById('progress').innerHTML = "";
}
</script>