This commit is contained in:
jomjol
2025-02-26 22:00:27 +01:00
20 changed files with 959 additions and 713 deletions

View File

@@ -250,13 +250,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Frank Haverland</b></sub> <sub><b>Frank Haverland</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/Slider0007">
<img src="https://avatars.githubusercontent.com/u/115730895?v=4" width="100;" alt="Slider0007"/>
<br />
<sub><b>Slider0007</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/SybexX"> <a href="https://github.com/SybexX">
<img src="https://avatars.githubusercontent.com/u/587201?v=4" width="100;" alt="SybexX"/> <img src="https://avatars.githubusercontent.com/u/587201?v=4" width="100;" alt="SybexX"/>
@@ -264,6 +257,13 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>michael</b></sub> <sub><b>michael</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/Slider0007">
<img src="https://avatars.githubusercontent.com/u/115730895?v=4" width="100;" alt="Slider0007"/>
<br />
<sub><b>Slider0007</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/nliaudat"> <a href="https://github.com/nliaudat">
<img src="https://avatars.githubusercontent.com/u/6782613?v=4" width="100;" alt="nliaudat"/> <img src="https://avatars.githubusercontent.com/u/6782613?v=4" width="100;" alt="nliaudat"/>
@@ -368,6 +368,13 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>parhedberg</b></sub> <sub><b>parhedberg</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/fsck-block">
<img src="https://avatars.githubusercontent.com/u/58307481?v=4" width="100;" alt="fsck-block"/>
<br />
<sub><b>fsck-block</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/slovdahl"> <a href="https://github.com/slovdahl">
<img src="https://avatars.githubusercontent.com/u/1417619?v=4" width="100;" alt="slovdahl"/> <img src="https://avatars.githubusercontent.com/u/1417619?v=4" width="100;" alt="slovdahl"/>
@@ -389,13 +396,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>LordGuilly</b></sub> <sub><b>LordGuilly</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/bilalmirza74">
<img src="https://avatars.githubusercontent.com/u/84387676?v=4" width="100;" alt="bilalmirza74"/>
<br />
<sub><b>Bilal Mirza</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/muggenhor"> <a href="https://github.com/muggenhor">
<img src="https://avatars.githubusercontent.com/u/484066?v=4" width="100;" alt="muggenhor"/> <img src="https://avatars.githubusercontent.com/u/484066?v=4" width="100;" alt="muggenhor"/>
@@ -406,10 +406,17 @@ There are some ideas and feature requests which are not currently being pursued
</tr> </tr>
<tr> <tr>
<td align="center"> <td align="center">
<a href="https://github.com/ppisljar"> <a href="https://github.com/bilalmirza74">
<img src="https://avatars.githubusercontent.com/u/13629809?v=4" width="100;" alt="ppisljar"/> <img src="https://avatars.githubusercontent.com/u/84387676?v=4" width="100;" alt="bilalmirza74"/>
<br /> <br />
<sub><b>Peter Pisljar</b></sub> <sub><b>Bilal Mirza</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/AngryApostrophe">
<img src="https://avatars.githubusercontent.com/u/89547888?v=4" width="100;" alt="AngryApostrophe"/>
<br />
<sub><b>AngryApostrophe</b></sub>
</a> </a>
</td> </td>
<td align="center"> <td align="center">
@@ -426,6 +433,13 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Ranjana761</b></sub> <sub><b>Ranjana761</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/SURYANSH-RAI">
<img src="https://avatars.githubusercontent.com/u/79277130?v=4" width="100;" alt="SURYANSH-RAI"/>
<br />
<sub><b>SURYANSH RAI</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/SkylightXD"> <a href="https://github.com/SkylightXD">
<img src="https://avatars.githubusercontent.com/u/16561545?v=4" width="100;" alt="SkylightXD"/> <img src="https://avatars.githubusercontent.com/u/16561545?v=4" width="100;" alt="SkylightXD"/>
@@ -433,6 +447,8 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>SkylightXD</b></sub> <sub><b>SkylightXD</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/ottk3"> <a href="https://github.com/ottk3">
<img src="https://avatars.githubusercontent.com/u/5236802?v=4" width="100;" alt="ottk3"/> <img src="https://avatars.githubusercontent.com/u/5236802?v=4" width="100;" alt="ottk3"/>
@@ -447,8 +463,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Tobias Bieniek</b></sub> <sub><b>Tobias Bieniek</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/tkopczuk"> <a href="https://github.com/tkopczuk">
<img src="https://avatars.githubusercontent.com/u/101632?v=4" width="100;" alt="tkopczuk"/> <img src="https://avatars.githubusercontent.com/u/101632?v=4" width="100;" alt="tkopczuk"/>
@@ -477,6 +491,8 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>flox_x</b></sub> <sub><b>flox_x</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/gneluka"> <a href="https://github.com/gneluka">
<img src="https://avatars.githubusercontent.com/u/32097881?v=4" width="100;" alt="gneluka"/> <img src="https://avatars.githubusercontent.com/u/32097881?v=4" width="100;" alt="gneluka"/>
@@ -491,8 +507,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>kalwados</b></sub> <sub><b>kalwados</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/kub3let"> <a href="https://github.com/kub3let">
<img src="https://avatars.githubusercontent.com/u/95883234?v=4" width="100;" alt="kub3let"/> <img src="https://avatars.githubusercontent.com/u/95883234?v=4" width="100;" alt="kub3let"/>
@@ -521,13 +535,8 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>smartboart</b></sub> <sub><b>smartboart</b></sub>
</a> </a>
</td> </td>
<td align="center"> </tr>
<a href="https://github.com/AngryApostrophe"> <tr>
<img src="https://avatars.githubusercontent.com/u/89547888?v=4" width="100;" alt="AngryApostrophe"/>
<br />
<sub><b>AngryApostrophe</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/wetneb"> <a href="https://github.com/wetneb">
<img src="https://avatars.githubusercontent.com/u/309908?v=4" width="100;" alt="wetneb"/> <img src="https://avatars.githubusercontent.com/u/309908?v=4" width="100;" alt="wetneb"/>
@@ -535,8 +544,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Antonin Delpeuch</b></sub> <sub><b>Antonin Delpeuch</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/adarazs"> <a href="https://github.com/adarazs">
<img src="https://avatars.githubusercontent.com/u/6269603?v=4" width="100;" alt="adarazs"/> <img src="https://avatars.githubusercontent.com/u/6269603?v=4" width="100;" alt="adarazs"/>
@@ -572,6 +579,8 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Dave</b></sub> <sub><b>Dave</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/FarukhS52"> <a href="https://github.com/FarukhS52">
<img src="https://avatars.githubusercontent.com/u/129654632?v=4" width="100;" alt="FarukhS52"/> <img src="https://avatars.githubusercontent.com/u/129654632?v=4" width="100;" alt="FarukhS52"/>
@@ -579,8 +588,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Farookh Zaheer Siddiqui</b></sub> <sub><b>Farookh Zaheer Siddiqui</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/hex7c0"> <a href="https://github.com/hex7c0">
<img src="https://avatars.githubusercontent.com/u/4419146?v=4" width="100;" alt="hex7c0"/> <img src="https://avatars.githubusercontent.com/u/4419146?v=4" width="100;" alt="hex7c0"/>
@@ -616,6 +623,8 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>Joerg Rosenkranz</b></sub> <sub><b>Joerg Rosenkranz</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/Innovatorcloudy"> <a href="https://github.com/Innovatorcloudy">
<img src="https://avatars.githubusercontent.com/u/183274513?v=4" width="100;" alt="Innovatorcloudy"/> <img src="https://avatars.githubusercontent.com/u/183274513?v=4" width="100;" alt="Innovatorcloudy"/>
@@ -623,8 +632,6 @@ There are some ideas and feature requests which are not currently being pursued
<sub><b>KrishCode</b></sub> <sub><b>KrishCode</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/myxor"> <a href="https://github.com/myxor">
<img src="https://avatars.githubusercontent.com/u/1397377?v=4" width="100;" alt="myxor"/> <img src="https://avatars.githubusercontent.com/u/1397377?v=4" width="100;" alt="myxor"/>
@@ -652,6 +659,13 @@ There are some ideas and feature requests which are not currently being pursued
<br /> <br />
<sub><b>Michael Geissler</b></sub> <sub><b>Michael Geissler</b></sub>
</a> </a>
</td>
<td align="center">
<a href="https://github.com/ppisljar">
<img src="https://avatars.githubusercontent.com/u/13629809?v=4" width="100;" alt="ppisljar"/>
<br />
<sub><b>Peter Pisljar</b></sub>
</a>
</td> </td>
</tr> </tr>
<tbody> <tbody>

View File

@@ -6,11 +6,8 @@
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. CONDITIONS OF ANY KIND, either express or implied.
*/ */
#include "server_file.h" #include "server_file.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
@@ -58,7 +55,6 @@ struct file_server_data {
char scratch[SERVER_FILER_SCRATCH_BUFSIZE]; char scratch[SERVER_FILER_SCRATCH_BUFSIZE];
}; };
#include <iostream> #include <iostream>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
@@ -67,11 +63,9 @@ using namespace std;
string SUFFIX_ZW = "_0xge"; string SUFFIX_ZW = "_0xge";
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file); static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file);
static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file); static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file);
esp_err_t get_numbers_file_handler(httpd_req_t *req) esp_err_t get_numbers_file_handler(httpd_req_t *req)
{ {
std::string ret = flowctrl.getNumbersName(); std::string ret = flowctrl.getNumbersName();
@@ -87,7 +81,6 @@ esp_err_t get_numbers_file_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
esp_err_t get_data_file_handler(httpd_req_t *req) esp_err_t get_data_file_handler(httpd_req_t *req)
{ {
struct dirent *entry; struct dirent *entry;
@@ -131,7 +124,6 @@ esp_err_t get_data_file_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
esp_err_t get_tflite_file_handler(httpd_req_t *req) esp_err_t get_tflite_file_handler(httpd_req_t *req)
{ {
struct dirent *entry; struct dirent *entry;
@@ -175,12 +167,11 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
/* Send HTTP response with a run-time generated html consisting of /* Send HTTP response with a run-time generated html consisting of
* a list of all files and folders under the requested path. * a list of all files and folders under the requested path.
* In case of SPIFFS this returns empty list when path is any * In case of SPIFFS this returns empty list when path is any
* string other than '/', since SPIFFS doesn't support directories */ * string other than '/', since SPIFFS doesn't support directories */
static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char* uripath, bool readonly) static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char *uripath, bool readonly)
{ {
char entrypath[FILE_PATH_MAX]; char entrypath[FILE_PATH_MAX];
char entrysize[16]; char entrysize[16];
@@ -192,82 +183,85 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
char dirpath_corrected[FILE_PATH_MAX]; char dirpath_corrected[FILE_PATH_MAX];
strcpy(dirpath_corrected, dirpath); strcpy(dirpath_corrected, dirpath);
file_server_data * server_data = (file_server_data *) req->user_ctx; file_server_data *server_data = (file_server_data *)req->user_ctx;
if ((strlen(dirpath_corrected)-1) > strlen(server_data->base_path)) // if dirpath is not mountpoint, the last "\" needs to be removed
dirpath_corrected[strlen(dirpath_corrected)-1] = '\0';
DIR *dir = opendir(dirpath_corrected); if ((strlen(dirpath_corrected) - 1) > strlen(server_data->base_path)) {
// if dirpath is not mountpoint, the last "\" needs to be removed
dirpath_corrected[strlen(dirpath_corrected) - 1] = '\0';
}
DIR *pdir = opendir(dirpath_corrected);
const size_t dirpath_len = strlen(dirpath); const size_t dirpath_len = strlen(dirpath);
ESP_LOGD(TAG, "Dirpath: <%s>, Pathlength: %d", dirpath, dirpath_len); ESP_LOGD(TAG, "Dirpath: <%s>, Pathlength: %d", dirpath, dirpath_len);
/* Retrieve the base path of file storage to construct the full path */ // Retrieve the base path of file storage to construct the full path
strlcpy(entrypath, dirpath, sizeof(entrypath)); strlcpy(entrypath, dirpath, sizeof(entrypath));
ESP_LOGD(TAG, "entrypath: <%s>", entrypath); ESP_LOGD(TAG, "entrypath: <%s>", entrypath);
if (!dir) { if (!pdir) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat dir: " + std::string(dirpath) + "!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat dir: " + std::string(dirpath) + "!");
/* Respond with 404 Not Found */ // Respond with 404 Not Found
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404()); httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
return ESP_FAIL; return ESP_FAIL;
} }
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
/* Send HTML file header */ // Send HTML file header
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>"); httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html lang=\"en\" xml:lang=\"en\"><head>");
httpd_resp_sendstr_chunk(req, "<link href=\"/file_server.css\" rel=\"stylesheet\">");
httpd_resp_sendstr_chunk(req, "<link href=\"/firework.css\" rel=\"stylesheet\">");
httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/jquery-3.6.0.min.js\"></script>");
httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/firework.js\"></script></head>");
///////////////////////////////////////////////// httpd_resp_sendstr_chunk(req, "<body>");
if (!readonly) {
FILE *fd = fopen("/sdcard/html/file_server.html", "r"); httpd_resp_sendstr_chunk(req, "<table class=\"fixed\" border=\"0\" width=100% style=\"font-family: arial\">");
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch; httpd_resp_sendstr_chunk(req, "<tr><td style=\"vertical-align: top;width: 300px;\"><h2>Fileserver</h2></td>"
size_t chunksize; "<td rowspan=\"2\"><table border=\"0\" style=\"width:100%\"><tr><td style=\"width:80px\">"
do { "<label for=\"newfile\">Source</label></td><td colspan=\"2\">"
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd); "<input id=\"newfile\" type=\"file\" onchange=\"setpath()\" style=\"width:100%;\"></td></tr>"
// ESP_LOGD(TAG, "Chunksize %d", chunksize); "<tr><td><label for=\"filepath\">Destination</label></td><td>"
if (chunksize > 0){ "<input id=\"filepath\" type=\"text\" style=\"width:94%;\"></td><td>"
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { "<button id=\"upload\" type=\"button\" class=\"button\" onclick=\"upload()\">Upload</button></td></tr>"
fclose(fd); "</table></td></tr><tr></tr><tr><td colspan=\"2\">"
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File sending failed!"); "<button style=\"font-size:16px; padding: 5px 10px\" id=\"dirup\" type=\"button\" onclick=\"dirup()\""
return ESP_FAIL; "disabled>&#129145; Directory up</button><span style=\"padding-left:15px\" id=\"currentpath\">"
} "</span></td></tr>");
} httpd_resp_sendstr_chunk(req, "</table>");
} while (chunksize != 0);
fclose(fd); httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/file_server.js\"></script>");
// ESP_LOGI(TAG, "File sending complete"); httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\">initFileServer();</script>");
}
///////////////////////////////
std::string _zw = std::string(dirpath); std::string _zw = std::string(dirpath);
_zw = _zw.substr(8, _zw.length() - 8); _zw = _zw.substr(8, _zw.length() - 8);
_zw = "/delete/" + _zw + "?task=deldircontent"; _zw = "/delete/" + _zw + "?task=deldircontent";
// Send file-list table definition and column labels
httpd_resp_sendstr_chunk(req, "<table id=\"files_table\">"
"<col width=\"800px\"><col width=\"300px\"><col width=\"300px\"><col width=\"100px\">"
"<thead><tr><th>Name</th><th>Type</th><th>Size</th>");
/* Send file-list table definition and column labels */
httpd_resp_sendstr_chunk(req,
"<table id=\"files_table\">"
"<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
"<thead><tr><th>Name</th><th>Type</th><th>Size</th>");
if (!readonly) { if (!readonly) {
httpd_resp_sendstr_chunk(req, "<th>" httpd_resp_sendstr_chunk(req, "<th><form method=\"post\" action=\"");
"<form method=\"post\" action=\"");
httpd_resp_sendstr_chunk(req, _zw.c_str()); httpd_resp_sendstr_chunk(req, _zw.c_str());
httpd_resp_sendstr_chunk(req, httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">DELETE ALL!</button></form></th></tr>");
"\"><button type=\"submit\">DELETE ALL!</button></form>"
"</th></tr>");
} }
httpd_resp_sendstr_chunk(req, "</thead><tbody>\n"); httpd_resp_sendstr_chunk(req, "</thead><tbody>\n");
/* Iterate over all files / folders and fetch their names and sizes */ // Iterate over all files / folders and fetch their names and sizes
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(pdir)) != NULL) {
if (strcmp("wlan.ini", entry->d_name) != 0 ) // wlan.ini soll nicht angezeigt werden! // wlan.ini soll nicht angezeigt werden!
{ if (strcmp("wlan.ini", entry->d_name) != 0) {
entrytype = (entry->d_type == DT_DIR ? "directory" : "file"); entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len); strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
ESP_LOGD(TAG, "Entrypath: %s", entrypath); ESP_LOGD(TAG, "Entrypath: %s", entrypath);
if (stat(entrypath, &entry_stat) == -1) { if (stat(entrypath, &entry_stat) == -1) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat " + string(entrytype) + ": " + string(entry->d_name)); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat " + std::string(entrytype) + ": " + std::string(entry->d_name));
continue; continue;
} }
@@ -283,22 +277,25 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
} }
} }
ESP_LOGI(TAG, "Found %s: %s (%s bytes)", entrytype, entry->d_name, entrysize); ESP_LOGD(TAG, "Found %s: %s (%s bytes)", entrytype, entry->d_name, entrysize);
/* Send chunk of HTML file containing table entries with file name and size */ // Send chunk of HTML file containing table entries with file name and size
httpd_resp_sendstr_chunk(req, "<tr><td><a href=\""); httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
httpd_resp_sendstr_chunk(req, "/fileserver"); httpd_resp_sendstr_chunk(req, "/fileserver");
httpd_resp_sendstr_chunk(req, uripath); httpd_resp_sendstr_chunk(req, uripath);
httpd_resp_sendstr_chunk(req, entry->d_name); httpd_resp_sendstr_chunk(req, entry->d_name);
if (entry->d_type == DT_DIR) { if (entry->d_type == DT_DIR) {
httpd_resp_sendstr_chunk(req, "/"); httpd_resp_sendstr_chunk(req, "/");
} }
httpd_resp_sendstr_chunk(req, "\">"); httpd_resp_sendstr_chunk(req, "\">");
httpd_resp_sendstr_chunk(req, entry->d_name); httpd_resp_sendstr_chunk(req, entry->d_name);
httpd_resp_sendstr_chunk(req, "</a></td><td>"); httpd_resp_sendstr_chunk(req, "</a></td><td>");
httpd_resp_sendstr_chunk(req, entrytype); httpd_resp_sendstr_chunk(req, entrytype);
httpd_resp_sendstr_chunk(req, "</td><td>"); httpd_resp_sendstr_chunk(req, "</td><td>");
httpd_resp_sendstr_chunk(req, entrysize); httpd_resp_sendstr_chunk(req, entrysize);
if (!readonly) { if (!readonly) {
httpd_resp_sendstr_chunk(req, "</td><td>"); httpd_resp_sendstr_chunk(req, "</td><td>");
httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete"); httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
@@ -306,31 +303,28 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
httpd_resp_sendstr_chunk(req, entry->d_name); httpd_resp_sendstr_chunk(req, entry->d_name);
httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>"); httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>");
} }
httpd_resp_sendstr_chunk(req, "</td></tr>\n"); httpd_resp_sendstr_chunk(req, "</td></tr>\n");
} }
} }
closedir(dir);
/* Finish the file list table */ closedir(pdir);
// Finish the file list table
httpd_resp_sendstr_chunk(req, "</tbody></table>"); httpd_resp_sendstr_chunk(req, "</tbody></table>");
/* Send remaining chunk of HTML file to complete it */ // Send remaining chunk of HTML file to complete it
httpd_resp_sendstr_chunk(req, "</body></html>"); httpd_resp_sendstr_chunk(req, "</body></html>");
/* Send empty chunk to signal HTTP response completion */ // Send empty chunk to signal HTTP response completion
httpd_resp_sendstr_chunk(req, NULL); httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK; return ESP_OK;
} }
/*
#define IS_FILE_EXT(filename, ext) \
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
*/
static esp_err_t logfileact_get_full_handler(httpd_req_t *req) { static esp_err_t logfileact_get_full_handler(httpd_req_t *req) {
return send_logfile(req, true); return send_logfile(req, true);
} }
static esp_err_t logfileact_get_last_part_handler(httpd_req_t *req) { static esp_err_t logfileact_get_last_part_handler(httpd_req_t *req) {
return send_logfile(req, false); return send_logfile(req, false);
} }
@@ -339,7 +333,6 @@ static esp_err_t datafileact_get_full_handler(httpd_req_t *req) {
return send_datafile(req, true); return send_datafile(req, true);
} }
static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req) { static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req) {
return send_datafile(req, false); return send_datafile(req, false);
} }
@@ -424,7 +417,6 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
return ESP_OK; return ESP_OK;
} }
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file) static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
{ {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler"); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler");
@@ -510,7 +502,6 @@ static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
return ESP_OK; return ESP_OK;
} }
/* Handler to download a file kept on the server */ /* Handler to download a file kept on the server */
static esp_err_t download_get_handler(httpd_req_t *req) static esp_err_t download_get_handler(httpd_req_t *req)
{ {
@@ -528,7 +519,6 @@ static esp_err_t download_get_handler(httpd_req_t *req)
// filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path, // filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
// req->uri, sizeof(filepath)); // req->uri, sizeof(filepath));
if (!filename) { if (!filename) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Filename is too long"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Filename is too long");
/* Respond with 414 Error */ /* Respond with 414 Error */
@@ -759,7 +749,6 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
httpd_resp_set_hdr(req, "Location", directory.c_str()); httpd_resp_set_hdr(req, "Location", directory.c_str());
httpd_resp_sendstr(req, "File uploaded successfully"); httpd_resp_sendstr(req, "File uploaded successfully");
return ESP_OK; return ESP_OK;
} }
@@ -770,7 +759,6 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
char filepath[FILE_PATH_MAX]; char filepath[FILE_PATH_MAX];
struct stat file_stat; struct stat file_stat;
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
char _query[200]; char _query[200];
char _valuechar[30]; char _valuechar[30];
@@ -893,13 +881,11 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
} }
} }
httpd_resp_set_hdr(req, "Location", directory.c_str()); httpd_resp_set_hdr(req, "Location", directory.c_str());
httpd_resp_sendstr(req, "File successfully deleted"); httpd_resp_sendstr(req, "File successfully deleted");
return ESP_OK; return ESP_OK;
} }
void delete_all_in_directory(std::string _directory) void delete_all_in_directory(std::string _directory)
{ {
struct dirent *entry; struct dirent *entry;
@@ -1137,8 +1123,6 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
ESP_LOGD(TAG, "Success."); ESP_LOGD(TAG, "Success.");
} }
void register_server_file_uri(httpd_handle_t server, const char *base_path) void register_server_file_uri(httpd_handle_t server, const char *base_path)
{ {
static struct file_server_data *server_data = NULL; static struct file_server_data *server_data = NULL;
@@ -1164,8 +1148,6 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
strlcpy(server_data->base_path, base_path, strlcpy(server_data->base_path, base_path,
sizeof(server_data->base_path)); sizeof(server_data->base_path));
/* URI handler for getting uploaded files */ /* URI handler for getting uploaded files */
// char zw[sizeof(serverprefix)+1]; // char zw[sizeof(serverprefix)+1];
// strcpy(zw, serverprefix); // strcpy(zw, serverprefix);
@@ -1180,7 +1162,6 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
}; };
httpd_register_uri_handler(server, &file_download); httpd_register_uri_handler(server, &file_download);
httpd_uri_t file_datafileact = { httpd_uri_t file_datafileact = {
.uri = "/datafileact", // Match all URIs of type /path/to/file .uri = "/datafileact", // Match all URIs of type /path/to/file
.method = HTTP_GET, .method = HTTP_GET,
@@ -1189,7 +1170,6 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
}; };
httpd_register_uri_handler(server, &file_datafileact); httpd_register_uri_handler(server, &file_datafileact);
httpd_uri_t file_datafile_last_part_handle = { httpd_uri_t file_datafile_last_part_handle = {
.uri = "/data", // Match all URIs of type /path/to/file .uri = "/data", // Match all URIs of type /path/to/file
.method = HTTP_GET, .method = HTTP_GET,
@@ -1206,7 +1186,6 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
}; };
httpd_register_uri_handler(server, &file_logfileact); httpd_register_uri_handler(server, &file_logfileact);
httpd_uri_t file_logfile_last_part_handle = { httpd_uri_t file_logfile_last_part_handle = {
.uri = "/log", // Match all URIs of type /path/to/file .uri = "/log", // Match all URIs of type /path/to/file
.method = HTTP_GET, .method = HTTP_GET,
@@ -1215,7 +1194,6 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
}; };
httpd_register_uri_handler(server, &file_logfile_last_part_handle); httpd_register_uri_handler(server, &file_logfile_last_part_handle);
/* URI handler for uploading files to server */ /* URI handler for uploading files to server */
httpd_uri_t file_upload = { httpd_uri_t file_upload = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file .uri = "/upload/*", // Match all URIs of type /upload/path/to/file
@@ -1233,5 +1211,4 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
.user_ctx = server_data // Pass server data as context .user_ctx = server_data // Pass server data as context
}; };
httpd_register_uri_handler(server, &file_delete); httpd_register_uri_handler(server, &file_delete);
} }

View File

@@ -1,4 +1,6 @@
#include "openmetrics.h" #include "openmetrics.h"
#include "functional"
#include "esp_log.h"
/** /**
* create a singe metric from the given input * create a singe metric from the given input
@@ -10,10 +12,66 @@ std::string createMetric(const std::string &metricName, const std::string &help,
metricName + " " + value + "\n"; metricName + " " + value + "\n";
} }
typedef struct sequence_metric {
const char *name;
const char *help;
const char *type;
std::function<std::string(NumberPost *number)> valueFunc;
} sequence_metric_t;
sequence_metric_t sequenceMetrics[4] = {
{ "flow_value", "current value of meter readout", "gauge", [](NumberPost *number)-> std::string {return number->ReturnValue;} },
{ "flow_raw_value", "current raw value of meter readout", "gauge", [](NumberPost *number)-> std::string {return number->ReturnRawValue;} },
{ "flow_pre_value", "previous value of meter readout", "gauge", [](NumberPost *number)-> std::string {return number->ReturnPreValue;} },
{ "flow_error", "Error message text != 'no error'", "gauge", [](NumberPost *number)-> std::string {return number->ErrorMessageText.compare("no error") == 0 ? "0" : "1";} },
};
std::string createSequenceMetrics(std::string prefix, const std::vector<NumberPost *> &numbers)
{
std::string result;
for (int i = 0; i<sizeof(sequenceMetrics)/sizeof(sequence_metric_t);i++)
{
std::string res;
for (const auto &number : numbers)
{
std::string value = sequenceMetrics[i].valueFunc(number);
if (value.find("N") != std::string::npos) {
value = "NaN";
}
ESP_LOGD("METRICS", "metric=%s, name=%s, value = %s ",sequenceMetrics[i].name,number->name.c_str(), value.c_str());
// only valid data is reported (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#missing-data)
if (value.length() > 0)
{
auto label = number->name;
// except newline, double quote, and backslash (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#abnf)
// to keep it simple, these characters are just removed from the label
replaceAll(label, "\\", "");
replaceAll(label, "\"", "");
replaceAll(label, "\n", "");
res += prefix + "_" + sequenceMetrics[i].name + "{sequence=\"" + label + "\"} " + value + "\n";
}
}
// prepend metadata if a valid metric was created
if (res.length() > 0)
{
res = "# HELP " + prefix + "_" + sequenceMetrics[i].name + " " + sequenceMetrics[i].help + "\n"
+ "# TYPE " + prefix + "_" + sequenceMetrics[i].name + " " + sequenceMetrics[i].type + "\n"
+ res;
}
result += res;
}
return result;
}
/** /**
* Generate the MetricFamily from all available sequences * Generate the MetricFamily from all available sequences
* @returns the string containing the text wire format of the MetricFamily * @returns the string containing the text wire format of the MetricFamily
**/ **/
/*
std::string createSequenceMetrics(std::string prefix, const std::vector<NumberPost *> &numbers) std::string createSequenceMetrics(std::string prefix, const std::vector<NumberPost *> &numbers)
{ {
std::string res; std::string res;
@@ -41,3 +99,4 @@ std::string createSequenceMetrics(std::string prefix, const std::vector<NumberPo
} }
return res; return res;
} }
*/

View File

@@ -37,23 +37,58 @@ void test_createSequenceMetrics()
NumberPost *number_1 = new NumberPost; NumberPost *number_1 = new NumberPost;
number_1->name = "main"; number_1->name = "main";
number_1->ReturnValue = "123.456"; number_1->ReturnValue = "123.456";
number_1->ReturnRawValue = "N23.456";
number_1->ReturnPreValue = "986.543";
number_1->ErrorMessageText = "";
NUMBERS.push_back(number_1); NUMBERS.push_back(number_1);
const std::string metricNamePrefix = "ai_on_the_edge_device"; const std::string metricNamePrefix = "ai_on_the_edge_device";
const std::string metricName = metricNamePrefix + "_flow_value"; const std::string metricName1 = metricNamePrefix + "_flow_value";
const std::string metricName2 = metricNamePrefix + "_flow_raw_value";
const std::string metricName3 = metricNamePrefix + "_flow_pre_value";
const std::string metricName4 = metricNamePrefix + "_flow_error";
std::string expected1 ;
expected1 = "# HELP " + metricName1 + " current value of meter readout\n# TYPE " + metricName1 + " gauge\n" +
metricName1 + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnValue + "\n";
expected1 += "# HELP " + metricName2 + " current raw value of meter readout\n# TYPE " + metricName2 + " gauge\n" +
metricName2 + "{sequence=\"" + number_1->name + "\"} " + "NaN" + "\n";
expected1 += "# HELP " + metricName3 + " previous value of meter readout\n# TYPE " + metricName3 + " gauge\n" +
metricName3 + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnPreValue + "\n";
expected1 += "# HELP " + metricName4 + " Error message text != 'no error'\n# TYPE " + metricName4 + " gauge\n" +
metricName4 + "{sequence=\"" + number_1->name + "\"} " + "1" + "\n";
std::string expected1 = "# HELP " + metricName + " current value of meter readout\n# TYPE " + metricName + " gauge\n" +
metricName + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnValue + "\n";
TEST_ASSERT_EQUAL_STRING(expected1.c_str(), createSequenceMetrics(metricNamePrefix, NUMBERS).c_str()); TEST_ASSERT_EQUAL_STRING(expected1.c_str(), createSequenceMetrics(metricNamePrefix, NUMBERS).c_str());
NumberPost *number_2 = new NumberPost; NumberPost *number_2 = new NumberPost;
number_2->name = "secondary"; number_2->name = "secondary";
number_2->ReturnValue = "1.0"; number_2->ReturnValue = "1.0";
number_2->ReturnRawValue = "01.000";
number_2->ReturnPreValue = "0.987";
number_2->ErrorMessageText = "no error";
NUMBERS.push_back(number_2); NUMBERS.push_back(number_2);
std::string expected2 = "# HELP " + metricName + " current value of meter readout\n# TYPE " + metricName + " gauge\n" + std::string expected2 ;
metricName + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnValue + "\n" + expected2 = "# HELP " + metricName1 + " current value of meter readout\n# TYPE " + metricName1 + " gauge\n" +
metricName + "{sequence=\"" + number_2->name + "\"} " + number_2->ReturnValue + "\n"; metricName1 + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnValue + "\n" +
metricName1 + "{sequence=\"" + number_2->name + "\"} " + number_2->ReturnValue + "\n";
expected2 += "# HELP " + metricName2 + " current raw value of meter readout\n# TYPE " + metricName2 + " gauge\n" +
metricName2 + "{sequence=\"" + number_1->name + "\"} " + "NaN" + "\n" +
metricName2 + "{sequence=\"" + number_2->name + "\"} " + number_2->ReturnRawValue + "\n";
expected2 += "# HELP " + metricName3 + " previous value of meter readout\n# TYPE " + metricName3 + " gauge\n" +
metricName3 + "{sequence=\"" + number_1->name + "\"} " + number_1->ReturnPreValue + "\n" +
metricName3 + "{sequence=\"" + number_2->name + "\"} " + number_2->ReturnPreValue + "\n";
expected2 += "# HELP " + metricName4 + " Error message text != 'no error'\n# TYPE " + metricName4 + " gauge\n" +
metricName4 + "{sequence=\"" + number_1->name + "\"} " + "1" + "\n" +
metricName4 + "{sequence=\"" + number_2->name + "\"} " + "0" + "\n";
TEST_ASSERT_EQUAL_STRING(expected2.c_str(), createSequenceMetrics(metricNamePrefix, NUMBERS).c_str()); TEST_ASSERT_EQUAL_STRING(expected2.c_str(), createSequenceMetrics(metricNamePrefix, NUMBERS).c_str());
} }

View File

@@ -0,0 +1,207 @@
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<title>Data Export (CSV)</title>
<meta charset="UTF-8"/>
<style>
h1 {font-size: 2em;}
h2 {font-size: 1.5em; margin-block-start: 0.0em; margin-block-end: 0.2em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
input[type=number] {
width: 138px;
padding: 10px 5px;
display: inline-block;
border: 1px solid #ccc;
font-size: 16px;
}
.button {
padding: 5px 10px;
width: 300px;
font-size: 16px;
}
</style>
</head>
<body style="font-family: arial; padding: 0px 10px;">
<h2>Data Export(CSV)</h2>
<p>With the following action the <a href="/fileserver/log/data/" target="_self">data</a> folder on the SD-card gets zipped and provided as a download.</p>
<button class="button" id="startExportData" type="button" onclick="startExportData()">Export Data</button>
<p></p>
<hr>
<p id=progress></p>
<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="jszip.min.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="FileSaver.min.js?v=$COMMIT_HASH"></script>
<script type="text/javascript">
function startExportData() {
document.getElementById("progress").innerHTML = "Creating Export Data...<br>\n";
// Get hostname
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/info?type=Hostname", false);
xhttp.send();
hostname = xhttp.responseText;
}
catch(err) {
setStatus("<span style=\"color: red\">Failed to fetch hostname: " + err.message + "!</span>");
return;
}
// get date/time
var dateTime = new Date().toJSON().slice(0,10) + "_" + new Date().toJSON().slice(11,19).replaceAll(":", "-");
zipFilename = hostname + "_" + dateTime + "_csv" + ".zip";
console.log(zipFilename);
// Get files list
setStatus("Fetching File List...");
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/fileserver/log/data/", false);
xhttp.send();
var parser = new DOMParser();
var content = parser.parseFromString(xhttp.responseText, 'text/html');
}
catch(err) {
setStatus("Failed to fetch files list: " + err.message);
return;
}
const list = content.querySelectorAll("a");
var urls = [];
for (a of list) {
url = a.getAttribute("href");
urls.push(getDomainname() + url);
}
// Pack as zip and download
try {
startExportZip(urls, zipFilename);
}
catch(err) {
setStatus("<span style=\"color: red\">Failed to zip files: " + err.message + "!</span>");
return;
}
}
function fetchFiles(urls, filesData, index, retry, zipFilename) {
url = urls[index];
if (retry == 0) {
setStatus("&nbsp;- " + getFilenameFromUrl(urls[index]) + " (" + (index+1) + "/" + urls.length + ")...");
}
else {
setStatus("<span style=\"color: gray\">&nbsp;&nbsp;&nbsp;Retrying (" + retry + ")...</span>");
}
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
if (retry == 0) { // Short timeout on first retry
xhr.timeout = 2000; // time in milliseconds
}
else if (retry == 1) { // longer timeout
xhr.timeout = 5000;
}
else if (retry == 2) { // longer timeout
xhr.timeout = 10000;
}
else if (retry == 3) { // longer timeout
xhr.timeout = 20000;
}
else { // very long timeout
xhr.timeout = 30000;
}
xhr.onload = () => { // Request finished
//console.log(url + " done");
filesData[index] = xhr.response;
if (index == urls.length - 1) {
setStatus("Fetched all files");
generateZipFile(urls, filesData, zipFilename);
return;
}
else { // Next file
fetchFiles(urls, filesData, index+1, 0, zipFilename);
}
};
xhr.onprogress = (e) => { // XMLHttpRequest progress ... extend timeout
xhr.timeout = xhr.timeout + 500;
};
xhr.onerror = (e) => { // XMLHttpRequest error loading
console.log("Error on fetching " + url + "!");
if (retry > 5) {
setStatus("<span style=\"color: red\">Data Export failed, please restart the device and try again!</span>");
}
else {
fetchFiles(urls, filesData, index, retry+1, zipFilename);
}
};
xhr.ontimeout = (e) => { // XMLHttpRequest timed out
console.log("Timeout on fetching " + url + "!");
if (retry > 5) {
setStatus("<span style=\"color: red\">Data Export failed, please restart the device and try again!</span>");
}
else {
fetchFiles(urls, filesData, index, retry+1, zipFilename);
}
};
xhr.send(null);
}
function generateZipFile(urls, filesData, zipFilename) {
setStatus("Creating Zip File...");
var zip = new JSZip();
for (var i = 0; i < urls.length; i++) {
zip.file(getFilenameFromUrl(urls[i]), filesData[i]);
}
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, zipFilename);
});
setStatus("Data Export completed");
}
const startExportZip = (urls, zipFilename) => {
if(!urls) { return; }
console.log(urls);
urlIndex = 0;
setStatus("Fetching files...");
fetchFiles(urls, [], 0, 0, zipFilename);
};
function setStatus(status) {
console.log(status);
document.getElementById("progress").innerHTML += status + "<br>\n";
}
function getFilenameFromUrl(url) {
return filename = url.substring(url.lastIndexOf('/')+1);
}
</script>
</body>
</html>

View File

@@ -79,6 +79,18 @@
transform: translate(-50%,-50%); transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%);
} }
#reboot_button {
float: none;
background-color: #f44336;
color: white;
padding: 5px;
border-radius:
5px; font-weight: bold;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style> </style>
<link href="firework.css?v=$COMMIT_HASH" rel="stylesheet"> <link href="firework.css?v=$COMMIT_HASH" rel="stylesheet">
@@ -188,13 +200,11 @@
param; param;
function doReboot() { function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save your changes?")) { var stringota = domainname + "/reboot";
var stringota = domainname + "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
}
} }
function ChangeSelection(){ function ChangeSelection(){
@@ -215,50 +225,45 @@
document.getElementById("overlay").style.display = "block"; document.getElementById("overlay").style.display = "block";
document.getElementById("overlaytext").innerHTML = "Save Alignment Marker..."; document.getElementById("overlaytext").innerHTML = "Save Alignment Marker...";
if (confirm("Are you sure you want to save the new alignment marker configuration?")) { function sleep(ms) {
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms));
return new Promise(resolve => setTimeout(resolve, ms)); }
}
async function task() { async function task() {
while (true) { while (true) {
WriteConfigININew(); WriteConfigININew();
if (neueref1 == 1 && neueref2 == 1) { if (neueref1 == 1 && neueref2 == 1) {
UpdateConfigReferences(domainname); UpdateConfigReferences(domainname);
} }
else if (neueref1 == 1) { else if (neueref1 == 1) {
var anzneueref = 1; var anzneueref = 1;
UpdateConfigReference(anzneueref, domainname); UpdateConfigReference(anzneueref, domainname);
} }
else if (neueref2 == 1) { else if (neueref2 == 1) {
var anzneueref = 2; var anzneueref = 2;
UpdateConfigReference(anzneueref, domainname); UpdateConfigReference(anzneueref, domainname);
}
SaveConfigToServer(domainname);
document.getElementById("updatemarker").disabled = false;
// document.getElementById("savemarker").disabled = true;
// document.getElementById("enhancecontrast").disabled = true;
EnDisableItem(false, "savemarker", true);
EnDisableItem(false, "enhancecontrast", true);
document.getElementById("overlay").style.display = "none";
firework.launch('Alignment marker saved. They will get applied after next reboot', 'success', 5000);
return;
} }
}
setTimeout(function () { SaveConfigToServer(domainname);
// Delay so the overlay gets shown
task(); document.getElementById("updatemarker").disabled = false;
}, 1); // document.getElementById("savemarker").disabled = true;
} // document.getElementById("enhancecontrast").disabled = true;
else {
document.getElementById("overlay").style.display = "none"; EnDisableItem(false, "savemarker", true);
EnDisableItem(false, "enhancecontrast", true);
document.getElementById("overlay").style.display = "none";
firework.launch('Alignment marker saved. They will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
return;
}
} }
setTimeout(function () {
// Delay so the overlay gets shown
task();
}, 1);
} }
function EnhanceContrast() { function EnhanceContrast() {

View File

@@ -5,6 +5,20 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Analog ROI</title> <title>Analog ROI</title>
<style>
#reboot_button {
float: none;
background-color: #f44336;
color: white;
padding: 5px;
border-radius:
5px; font-weight: bold;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style>
<link href="edit_style.css" rel="stylesheet"> <link href="edit_style.css" rel="stylesheet">
<link href="firework.css?v=$COMMIT_HASH" rel="stylesheet"> <link href="firework.css?v=$COMMIT_HASH" rel="stylesheet">
@@ -185,13 +199,11 @@ The following settings are only used for easier setup, they are <b>not</b> persi
domainname = getDomainname(); domainname = getDomainname();
function doReboot() { function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save your changes?")) { var stringota = getDomainname() + "/reboot";
var stringota = getDomainname() + "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
}
} }
function EnDisableAnalog() { function EnDisableAnalog() {
@@ -331,16 +343,14 @@ The following settings are only used for easier setup, they are <b>not</b> persi
} }
function SaveToConfig() { function SaveToConfig() {
if (confirm("Are you sure you want to save the new analog ROI configuration?")) { //_zwcat = getConfigCategory();
//_zwcat = getConfigCategory(); cofcat["Analog"]["enabled"] = document.getElementById("Category_Analog_enabled").checked;
cofcat["Analog"]["enabled"] = document.getElementById("Category_Analog_enabled").checked; WriteConfigININew();
WriteConfigININew(); SaveConfigToServer(domainname);
SaveConfigToServer(domainname); UpdateROIs();
UpdateROIs(); document.getElementById("saveroi").disabled = true;
document.getElementById("saveroi").disabled = true;
firework.launch('Configuration saved. It will get applied after next reboot', 'success', 5000); firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
}
} }
function ShowMultiplier() { function ShowMultiplier() {

View File

@@ -20,6 +20,18 @@
textarea { textarea {
font-size: 15px; font-size: 15px;
} }
#reboot_button {
float: none;
background-color: #f44336;
color: white;
padding: 5px;
border-radius:
5px; font-weight: bold;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style> </style>
<link href="firework.css?v=$COMMIT_HASH" rel="stylesheet"> <link href="firework.css?v=$COMMIT_HASH" rel="stylesheet">
@@ -38,15 +50,8 @@
</td> </td>
</table> </table>
<table> <hr>
<td> <button class="button" onclick="saveTextAsFile()">Save Config</button>
<button class="button" onclick="saveTextAsFile()">Save Config</button>
</td>
<td>
<button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate changes</button>
</td>
</table>
<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script> <script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script> <script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
@@ -64,23 +69,19 @@
function saveTextAsFile() function saveTextAsFile()
{ {
if (confirm("Are you sure you want to save the configuration?")) { FileDeleteOnServer("/config/config.ini", domainname);
FileDeleteOnServer("/config/config.ini", domainname); var textToSave = document.getElementById("inputTextToSave").value;
var textToSave = document.getElementById("inputTextToSave").value; FileSendContent(textToSave, "/config/config.ini", domainname);
FileSendContent(textToSave, "/config/config.ini", domainname);
firework.launch('Configuration saved. It will get applied after next reboot', 'success', 5000); firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
}
} }
function doReboot() { function doReboot() {
if (confirm("Are you sure you want to reboot?")) { var stringota = "/reboot";
var stringota = "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
}
} }
LoadConfigNeu(); LoadConfigNeu();

View File

@@ -184,6 +184,18 @@
transform: translate(-50%,-50%); transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%);
} }
#reboot_button {
float: none;
background-color: #f44336;
color: white;
padding: 5px;
border-radius:
5px; font-weight: bold;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style> </style>
<link rel="stylesheet" href="mkdocs_theme.css?v=$COMMIT_HASH" /> <link rel="stylesheet" href="mkdocs_theme.css?v=$COMMIT_HASH" />
@@ -897,7 +909,7 @@
<tr style="margin-top:12px"> <tr style="margin-top:12px">
<td class="indent1" style="padding-top:25px" colspan="3"> <td class="indent1" style="padding-top:25px" colspan="3">
<b>Parameter per number sequence:</b> <b>The following parameters are configurable individually for each number sequence:</b>
<select <select
style="font-weight: bold; margin-left:17px" id="Numbers_value1" onchange="numberChanged()"> style="font-weight: bold; margin-left:17px" id="Numbers_value1" onchange="numberChanged()">
</select> </select>
@@ -1188,8 +1200,8 @@
<option value="energy_mwh">Energymeter (Value: MWh, Rate: MW)</option> <option value="energy_mwh">Energymeter (Value: MWh, Rate: MW)</option>
<option value="energy_gj">Energymeter (Value: GJ, Rate: GJ/h)</option> <option value="energy_gj">Energymeter (Value: GJ, Rate: GJ/h)</option>
<option value="temperature_c">Thermometer (Value: °C, Rate: °C/min)</option> <option value="temperature_c">Thermometer (Value: °C, Rate: °C/min)</option>
<option value="temperature_c">Thermometer (Value: °F, Rate: °F/min)</option> <option value="temperature_f">Thermometer (Value: °F, Rate: °F/min)</option>
<option value="temperature_c">Thermometer (Value: K, Rate: K/min)</option> <option value="temperature_k">Thermometer (Value: K, Rate: K/min)</option>
</select> </select>
</td> </td>
<td>$TOOLTIP_MQTT_MeterType</td> <td>$TOOLTIP_MQTT_MeterType</td>
@@ -1208,7 +1220,7 @@
<tr class="MQTTItem" style="margin-top:12px"> <tr class="MQTTItem" style="margin-top:12px">
<td class="indent1" style="padding-top:25px" colspan="3"> <td class="indent1" style="padding-top:25px" colspan="3">
<b>Parameter per number sequence:</b> <b>The following parameters are configurable individually for each number sequence:</b>
<select <select
style="font-weight: bold; margin-left:17px" id="NumbersMQTTIdx_value1" onchange="numberMQTTIdxChanged()"> style="font-weight: bold; margin-left:17px" id="NumbersMQTTIdx_value1" onchange="numberMQTTIdxChanged()">
</select> </select>
@@ -1937,11 +1949,11 @@
<!------------- Autotimer ------------------> <!------------- Autotimer ------------------>
<!--
<tr style="border-bottom: 2px solid lightgray;"> <tr style="border-bottom: 2px solid lightgray;">
<td colspan="3" style="padding-left: 0px; padding-bottom: 3px;"><h4>Auto Timer</h4></td> <td colspan="3" style="padding-left: 0px; padding-bottom: 3px;"><h4>Auto Timer</h4></td>
</tr> </tr>
<!--
<tr class="expert" unused_id="ex13"> <tr class="expert" unused_id="ex13">
<td class="indent1"> <td class="indent1">
<class id="AutoTimer_AutoStart_text" style="color:black;">Automatic Round Start</class> <class id="AutoTimer_AutoStart_text" style="color:black;">Automatic Round Start</class>
@@ -2110,14 +2122,9 @@
</tr> </tr>
</table> </table>
<table style="padding-top:10px"> <hr>
<td> <button class="button" onclick="saveTextAsFile()">Save Config</button>
<button class="button" onclick="saveTextAsFile()">Save Config</button>
</td>
<td>
<button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate changes</button>
</td>
</table>
</div> </div>
@@ -2673,18 +2680,16 @@ function saveTextAsFile() {
return; return;
} }
if (confirm("Are you sure you want to save the configuration?")) { ReadParameterAll();
ReadParameterAll(); WriteConfigININew();
WriteConfigININew(); SaveConfigToServer(domainname);
SaveConfigToServer(domainname);
firework.launch('Configuration saved. It will get applied after the next reboot!', 'success', 5000); firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
if (changeCamValue == 1) { if (changeCamValue == 1) {
camSettingsSet(); camSettingsSet();
firework.launch('You have changed the camera settings, so creating a new reference image and updating the alignment marks is mandatory!', 'success', 10000); firework.launch('You have changed the camera settings, creating a new reference image and updating the alignment marks is mandatory!', 'success', 5000);
} }
}
} }
function camSettingsSet(){ function camSettingsSet(){
@@ -2875,7 +2880,7 @@ function camSettingsSet(){
if (xhttp.responseText == "CamSettingsSet") { if (xhttp.responseText == "CamSettingsSet") {
document.getElementById("overlay").style.display = "none"; document.getElementById("overlay").style.display = "none";
firework.launch('Cam Settings saved', 'success', 2000); firework.launch('Cam Settings saved', 'success', 5000);
return; return;
} }
else { else {
@@ -2903,13 +2908,11 @@ function camSettingsSet(){
} }
function doReboot() { function doReboot() {
if (confirm("Are you sure you want to reboot?")) { var stringota = domainname + "/reboot";
var stringota = domainname + "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
}
} }
function FormatDecimalValue(_param, _cat, _name) { function FormatDecimalValue(_param, _cat, _name) {

View File

@@ -4,6 +4,19 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Digit ROI</title> <title>Digit ROI</title>
<style>
#reboot_button {
float: none;
background-color: #f44336;
color: white;
padding: 5px;
border-radius:
5px; font-weight: bold;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style>
<link href="edit_style.css" rel="stylesheet"> <link href="edit_style.css" rel="stylesheet">
<link href="firework.css?v=$COMMIT_HASH" rel="stylesheet"> <link href="firework.css?v=$COMMIT_HASH" rel="stylesheet">
@@ -204,13 +217,11 @@
domainname = getDomainname(); domainname = getDomainname();
function doReboot() { function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save your changes?")) { var stringota = getDomainname() + "/reboot";
var stringota = getDomainname() + "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
}
} }
function EnDisableDigits() { function EnDisableDigits() {
@@ -359,16 +370,14 @@
} }
function SaveToConfig() { function SaveToConfig() {
if (confirm("Are you sure you want to save the new digit ROI configuration?")) { // _zwcat = getConfigCategory();
// _zwcat = getConfigCategory(); cofcat["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked;
cofcat["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked; WriteConfigININew();
WriteConfigININew(); SaveConfigToServer(domainname);
SaveConfigToServer(domainname); UpdateROIs();
UpdateROIs(); document.getElementById("saveroi").disabled = true;
document.getElementById("saveroi").disabled = true;
firework.launch('Configuration saved. It will get applied after next reboot', 'success', 5000); firework.launch('Configuration saved. It will get applied after the next reboot!<br><br>\n<a id="reboot_button" onclick="doReboot()">reboot now</a>', 'success', 5000);
}
} }
function ShowMultiplier() { function ShowMultiplier() {

View File

@@ -395,22 +395,12 @@
<script type="text/javascript"> <script type="text/javascript">
var canvas = document.getElementById('canvas'), var canvas = document.getElementById('canvas'),
domainname = getDomainname(), domainname = getDomainname(),
context = canvas.getContext('2d'), context = canvas.getContext('2d'),
imageObj = new Image(), imageObj = new Image(),
isActReference = false, isActReference = false,
param, param,
category; category;
function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save the config?")) {
var stringota = domainname + "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function cameraParameterChanged() { function cameraParameterChanged() {
document.getElementById("savereferenceimage").disabled = true; document.getElementById("savereferenceimage").disabled = true;
@@ -738,7 +728,7 @@
if (xhttp.responseText == "CamSettingsSet") { if (xhttp.responseText == "CamSettingsSet") {
document.getElementById("overlay").style.display = "none"; document.getElementById("overlay").style.display = "none";
firework.launch('Cam Settings saved', 'success', 2000); firework.launch('Cam Settings saved', 'success', 5000);
return; return;
} }
else { else {

View File

@@ -0,0 +1,50 @@
h1 {font-size: 2em;}
h2 {font-size: 1.5em; margin-block-start: 0.0em; margin-block-end: 0.2em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
#files_table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#files_table td, #files_table th {
border: 1px solid #ddd;
padding: 8px;
}
#files_table tr:nth-child(even){
background-color: #f2f2f2;
}
#files_table tr:hover {
background-color: #ddd;
}
#files_table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color:lightgrey;
color: black;
}
input[type=file] {
padding: 5px 0px;
display: inline-block;
font-size: 16px;
}
input[type=text] {
padding: 5px 10px;
display: inline-block;
border: 1px solid #ccc;
font-size: 16px;
}
.button {
padding: 4px 10px;
width: 100px;
font-size: 16px;
}

View File

@@ -1,206 +0,0 @@
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<link href="/firework.css?v=$COMMIT_HASH" rel="stylesheet">
<script type="text/javascript" src="/jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="/firework.js?v=$COMMIT_HASH"></script>
<style>
h1 {font-size: 2em;}
h2 {font-size: 1.5em; margin-block-start: 0.0em; margin-block-end: 0.2em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
#files_table {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
}
#files_table td, #files_table th {
border: 1px solid #ddd;
padding: 8px;
}
#files_table tr:nth-child(even){
background-color: #f2f2f2;
}
#files_table tr:hover {
background-color: #ddd;
}
#files_table th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color:lightgrey;
color: black;
}
input[type=file] {
padding: 5px 0px;
display: inline-block;
font-size: 16px;
}
input[type=text] {
padding: 5px 10px;
display: inline-block;
border: 1px solid #ccc;
font-size: 16px;
}
.button {
padding: 4px 10px;
width: 100px;
font-size: 16px;
}
</style>
</head>
</body>
<table class="fixed" border="0" width=100% style="font-family: arial">
<tr>
<td style="vertical-align: top;width: 300px;">
<h2>Fileserver</h2>
</td>
<td rowspan="2">
<table border="0" style="width:100%">
<tr>
<td style="width:80px">
<label for="newfile">Source</label>
</td>
<td colspan="2">
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
</td>
</tr>
<tr>
<td>
<label for="filepath">Destination</label>
</td>
<td>
<input id="filepath" type="text" style="width:94%;">
</td>
<td>
<button id="upload" type="button" class="button" onclick="upload()">Upload</button>
</td>
</tr>
</table>
</td>
</tr>
<tr></tr>
<tr>
<td colspan="2">
<button style="font-size:16px; padding: 5px 10px" id="dirup" type="button" onclick="dirup()" disabled>&#129145; Directory up</button>
<span style="padding-left:15px" id="currentpath"></span>
</td>
</tr>
</table>
<script type="text/javascript" src="/common.js?v=$COMMIT_HASH"></script>
<script type="text/javascript">
function setpath() {
var fileserverpraefix = "/fileserver";
var anz_zeichen_fileserver = fileserverpraefix.length;
var default_path = window.location.pathname.substring(anz_zeichen_fileserver) + document.getElementById("newfile").files[0].name;
document.getElementById("filepath").value = default_path;
}
function dirup() {
var str = window.location.href;
str = str.substring(0, str.length-1);
var zw = str.indexOf("/");
var found = zw;
while (zw >= 0)
{
zw = str.indexOf("/", found+1);
if (zw >= 0)
found = zw;
}
var res = str.substring(0, found+1);
window.location.href = res;
}
function upload() {
var filePath = document.getElementById("filepath").value;
var upload_path = "/upload/" + filePath;
var fileInput = document.getElementById("newfile").files;
/* Max size of an individual file. Make sure this
* value is same as that set in file_server.c */
var MAX_FILE_SIZE = 8000*1024;
var MAX_FILE_SIZE_STR = "8000KB";
if (fileInput.length == 0) {
firework.launch('No file selected!', 'danger', 30000);
} else if (filePath.length == 0) {
firework.launch('File path on server is not set!', 'danger', 30000);
} else if (filePath.length > 100) {
firework.launch('Filename is to long! Max 100 characters.', 'danger', 30000);
} else if (filePath.indexOf(' ') >= 0) {
firework.launch('File path on server cannot have spaces!', 'danger', 30000);
} else if (filePath[filePath.length-1] == '/') {
firework.launch('File name not specified after path!', 'danger', 30000);
} else if (fileInput[0].size > MAX_FILE_SIZE) {
firework.launch("File size must be less than " + MAX_FILE_SIZE_STR + "!", 'danger', 30000);
} else {
document.getElementById("newfile").disabled = true;
document.getElementById("filepath").disabled = true;
document.getElementById("upload").disabled = true;
var file = fileInput[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.open();
document.write(xhttp.responseText);
document.close();
firework.launch('File upload completed', 'success', 5000);
} else if (xhttp.status == 0) {
firework.launch('Server closed the connection abruptly!', 'danger', 30000);
UpdatePage(false);
} else {
firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
UpdatePage(false);
}
}
};
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
function checkAtRootLevel(res) {
if (getPath() == "/fileserver/") { // Already at root level
document.getElementById("dirup").disabled = true;
console.log("Already on sd-card root level!");
return true;
}
document.getElementById("dirup").disabled = false;
return false;
}
function getPath() {
return window.location.pathname.replace(/\/+$/, '') + "/"
}
checkAtRootLevel();
console.log("Current path: " + getPath().replace("/fileserver", ""));
document.getElementById("currentpath").innerHTML = "Current path: <b>" + getPath().replace("/fileserver", "") + "</b>";
document.cookie = "page=" + getPath() + "; path=/";
</script>
</body>
</html>

View File

@@ -0,0 +1,93 @@
function setpath() {
var fileserverpraefix = "/fileserver";
var anz_zeichen_fileserver = fileserverpraefix.length;
var default_path = window.location.pathname.substring(anz_zeichen_fileserver) + document.getElementById("newfile").files[0].name;
document.getElementById("filepath").value = default_path;
}
function dirup() {
var str = window.location.href;
str = str.substring(0, str.length-1);
var zw = str.indexOf("/");
var found = zw;
while (zw >= 0) {
zw = str.indexOf("/", found+1);
if (zw >= 0) {
found = zw;
}
}
var res = str.substring(0, found+1);
window.location.href = res;
}
function upload() {
var filePath = document.getElementById("filepath").value;
var upload_path = "/upload/" + filePath;
var fileInput = document.getElementById("newfile").files;
// Max size of an individual file. Make sure this value is same as that set in file_server.c
var MAX_FILE_SIZE = 8000*1024;
var MAX_FILE_SIZE_STR = "8000KB";
if (fileInput.length == 0) {
firework.launch('No file selected!', 'danger', 30000);
} else if (filePath.length == 0) {
firework.launch('File path on server is not set!', 'danger', 30000);
} else if (filePath.length > 100) {
firework.launch('Filename is to long! Max 100 characters.', 'danger', 30000);
} else if (filePath.indexOf(' ') >= 0) {
firework.launch('File path on server cannot have spaces!', 'danger', 30000);
} else if (filePath[filePath.length-1] == '/') {
firework.launch('File name not specified after path!', 'danger', 30000);
} else if (fileInput[0].size > MAX_FILE_SIZE) {
firework.launch("File size must be less than " + MAX_FILE_SIZE_STR + "!", 'danger', 30000);
} else {
document.getElementById("newfile").disabled = true;
document.getElementById("filepath").disabled = true;
document.getElementById("upload").disabled = true;
var file = fileInput[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.open();
document.write(xhttp.responseText);
document.close();
firework.launch('File upload completed', 'success', 5000);
} else if (xhttp.status == 0) {
firework.launch('Server closed the connection abruptly!', 'danger', 30000);
UpdatePage(false);
} else {
firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
UpdatePage(false);
}
}
};
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
function checkAtRootLevel(res) {
if (getPath() == "/fileserver/") {
// Already at root level
document.getElementById("dirup").disabled = true;
console.log("Already on sd-card root level!");
return true;
}
document.getElementById("dirup").disabled = false;
return false;
}
function getPath() {
return window.location.pathname.replace(/\/+$/, '') + "/"
}
function initFileServer() {
checkAtRootLevel();
console.log("Current path: " + getPath().replace("/fileserver", ""));
document.getElementById("currentpath").innerHTML = "Current path: <b>" + getPath().replace("/fileserver", "") + "</b>";
document.cookie = "page=" + getPath() + "; path=/";
}

View File

@@ -142,6 +142,7 @@
<li><a href="#" onclick="loadPage('graph.html?v=$COMMIT_HASH');">Data Graph</a></li> <li><a href="#" onclick="loadPage('graph.html?v=$COMMIT_HASH');">Data Graph</a></li>
<li><a href="#" onclick="loadPage('data.html?v=$COMMIT_HASH');">Data Table</a></li> <li><a href="#" onclick="loadPage('data.html?v=$COMMIT_HASH');">Data Table</a></li>
<li><a href="#" onclick="loadPage(getDomainname() + '/fileserver/log/data/');">Data Files</a></li> <li><a href="#" onclick="loadPage(getDomainname() + '/fileserver/log/data/');">Data Files</a></li>
<li><a href="#" onclick="loadPage('data_export.html?v=$COMMIT_HASH');">Data Export</a></li>
</ul> </ul>
</li> </li>

View File

@@ -34,13 +34,11 @@ p {font-size: 1em;}
<script> <script>
function doReboot() { function doReboot() {
// if (confirm("Are you sure you want to reboot the ESP32?")) { var stringota = getDomainname() + "/reboot";
var stringota = getDomainname() + "/reboot"; window.location = stringota;
window.location = stringota; window.location.href = stringota;
window.location.href = stringota; window.location.assign(stringota);
window.location.assign(stringota); window.location.replace(stringota);
window.location.replace(stringota);
// }
} }
</script> </script>

BIN
sd-card/html/searchicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

View File

@@ -8,7 +8,7 @@
} }
#myInput { #myInput {
background-image: url('/css/searchicon.png'); background-image: url('searchicon.png');
background-position: 10px 10px; background-position: 10px 10px;
background-repeat: no-repeat; background-repeat: no-repeat;
width: 100%; width: 100%;

View File

@@ -29,7 +29,7 @@
// var xhttp = new XMLHttpRequest(); // var xhttp = new XMLHttpRequest();
// xhttp.onreadystatechange = function() {if (xhttp.readyState == 4) {if (xhttp.status == 200) {document.reload();}}}; // xhttp.onreadystatechange = function() {if (xhttp.readyState == 4) {if (xhttp.status == 200) {document.reload();}}};
if (!file.name.includes("remote-setup")){ 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?")) if (!confirm("The zip file name should contain \"...remote-setup...\". Are you sure you have downloaded the correct file?"))
return; return;
} }
@@ -41,7 +41,7 @@ if (!file.name.includes("remote-setup")){
var file = document.getElementById("newfile").files[0]; var file = document.getElementById("newfile").files[0];
if (!file.name.includes("remote-setup")) 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?")) if (!confirm("The zip file name should contain \"...remote-setup...\". Are you sure you have downloaded the correct file?"))
return; return;
} }