mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-06 19:46:54 +03:00
Improve initial setup proc (#1692)
* Initial Test * Initial functional version.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
489
code/main/softAP.cpp
Normal 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
19
code/main/softAP.h
Normal 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
|
||||
97
sd-card/html/wlan_config.html
Normal file
97
sd-card/html/wlan_config.html
Normal 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>
|
||||
Reference in New Issue
Block a user