diff --git a/README.md b/README.md index 0cd19133..65041ad7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,11 @@ A 3d-printable housing can be found here: https://www.thingiverse.com/thing:4571 -##### Rolling - (2020-11-20) +##### Rolling - (2020-11-21) + +* Implementation of standardized access to current logfile via `http://IP-ADRESS/logfileact` - implemented via internal redirect + +2020-11-20 * Restructuring of code to be compatible with pure ESP-IDF development environment diff --git a/code/components/jomjol_fileserver_ota/server_file.cpp b/code/components/jomjol_fileserver_ota/server_file.cpp index 69471839..3c8eb2dc 100644 --- a/code/components/jomjol_fileserver_ota/server_file.cpp +++ b/code/components/jomjol_fileserver_ota/server_file.cpp @@ -216,6 +216,70 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0) +static esp_err_t logfileact_get_handler(httpd_req_t *req) +{ + LogFile.WriteToFile("logfileact_get_handler"); + char filepath[FILE_PATH_MAX]; + FILE *fd = NULL; + struct stat file_stat; + printf("uri: %s\n", req->uri); + + const char filename = 'log_current.txt'; + + printf("uri: %s, filename: %s, filepath: %s\n", req->uri, &filename, filepath); + + std::string currentfilename = LogFile.GetCurrentFileName(); + + + fd = fopen(currentfilename.c_str(), "r"); + if (!fd) { + ESP_LOGE(TAG, "Failed to read existing file : %s", filepath); + /* Respond with 500 Internal Server Error */ + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file"); + return ESP_FAIL; + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + +// ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size); + set_content_type_from_file(req, &filename); + + /* Retrieve the pointer to scratch buffer for temporary storage */ + char *chunk = ((struct file_server_data *)req->user_ctx)->scratch; + size_t chunksize; + do { + /* Read file in chunks into the scratch buffer */ + chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd); + + /* Send the buffer contents as HTTP response chunk */ + if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { + fclose(fd); + ESP_LOGE(TAG, "File sending failed!"); + /* Abort sending file */ + httpd_resp_sendstr_chunk(req, NULL); + /* Respond with 500 Internal Server Error */ + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file"); + return ESP_FAIL; + } + + /* Keep looping till the whole file is sent */ + } while (chunksize != 0); + + /* Close file after sending complete */ + fclose(fd); + ESP_LOGI(TAG, "File sending complete"); + + /* Respond with an empty chunk to signal HTTP response completion */ + httpd_resp_send_chunk(req, NULL, 0); + return ESP_OK; +} + + + + + + + /* Handler to download a file kept on the server */ static esp_err_t download_get_handler(httpd_req_t *req) { @@ -707,6 +771,17 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path) }; httpd_register_uri_handler(server, &file_download); + + + httpd_uri_t file_logfileact = { + .uri = "/logfileact", // Match all URIs of type /path/to/file + .method = HTTP_GET, + .handler = logfileact_get_handler, + .user_ctx = server_data // Pass server data as context + }; + httpd_register_uri_handler(server, &file_logfileact); + + /* URI handler for uploading files to server */ httpd_uri_t file_upload = { .uri = "/upload/*", // Match all URIs of type /upload/path/to/file diff --git a/code/components/jomjol_logfile/ClassLogFile.cpp b/code/components/jomjol_logfile/ClassLogFile.cpp index ccb75cf0..78b0df19 100644 --- a/code/components/jomjol_logfile/ClassLogFile.cpp +++ b/code/components/jomjol_logfile/ClassLogFile.cpp @@ -75,6 +75,21 @@ void ClassLogFile::WriteToFile(std::string info, bool _time) WriteToDedicatedFile(logpath, info, _time); } +std::string ClassLogFile::GetCurrentFileName() +{ + time_t rawtime; + struct tm* timeinfo; + char buffer[30]; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + strftime(buffer, 30, logfile.c_str(), timeinfo); + std::string logpath = logroot + "/" + buffer; + + return logpath; +} + void ClassLogFile::RemoveOld() { if (retentionInDays == 0) { diff --git a/code/components/jomjol_logfile/ClassLogFile.h b/code/components/jomjol_logfile/ClassLogFile.h index 5915c329..8f7841ba 100644 --- a/code/components/jomjol_logfile/ClassLogFile.h +++ b/code/components/jomjol_logfile/ClassLogFile.h @@ -18,6 +18,8 @@ public: void WriteToFile(std::string info, bool _time = true); void WriteToDedicatedFile(std::string _fn, std::string info, bool _time = true); void RemoveOld(); + + std::string GetCurrentFileName(); }; extern ClassLogFile LogFile; \ No newline at end of file diff --git a/code/src/version.cpp b/code/src/version.cpp index 82f13c8b..a6e22e11 100644 --- a/code/src/version.cpp +++ b/code/src/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="1cba7d3"; +const char* GIT_REV="288910e"; const char* GIT_TAG=""; const char* GIT_BRANCH="rolling"; -const char* BUILD_TIME="2020-11-20 19:26"; \ No newline at end of file +const char* BUILD_TIME="2020-11-21 19:02"; \ No newline at end of file diff --git a/code/version.cpp b/code/version.cpp index ea927576..a6e22e11 100644 --- a/code/version.cpp +++ b/code/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="1cba7d3"; +const char* GIT_REV="288910e"; const char* GIT_TAG=""; const char* GIT_BRANCH="rolling"; -const char* BUILD_TIME="2020-11-20 19:25"; \ No newline at end of file +const char* BUILD_TIME="2020-11-21 19:02"; \ No newline at end of file diff --git a/firmware/bootloader.bin b/firmware/bootloader.bin index 36da412a..08cb7d4d 100644 Binary files a/firmware/bootloader.bin and b/firmware/bootloader.bin differ diff --git a/firmware/firmware.bin b/firmware/firmware.bin index 089b9d9a..b8d3a131 100644 Binary files a/firmware/firmware.bin and b/firmware/firmware.bin differ diff --git a/firmware/html.zip b/firmware/html.zip index 0d3efe60..d8637d3b 100644 Binary files a/firmware/html.zip and b/firmware/html.zip differ diff --git a/sd-card/config/dig0720s1.tflite b/sd-card/config/dig0720s1.tflite new file mode 100644 index 00000000..e0325e91 Binary files /dev/null and b/sd-card/config/dig0720s1.tflite differ diff --git a/sd-card/html/readconfigparam.js b/sd-card/html/readconfigparam.js new file mode 100644 index 00000000..8ed63055 --- /dev/null +++ b/sd-card/html/readconfigparam.js @@ -0,0 +1,525 @@ +function readconfig_Version(){ + return "1.0.0 - 20200910"; + } + +var config_gesamt; +var config_split; +var ref = new Array(2); +var digit = new Array(0); +var analog = new Array(0); +var initalrotate = new Object(); + +function MakeRefZW(zw, _basepath){ + url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=/img_tmp/ref_zw_org.jpg&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; + var xhttp = new XMLHttpRequest(); + try { + xhttp.open("GET", url, false); + xhttp.send(); } + catch (error) + { +// alert("Deleting Config.ini failed"); + } + FileCopyOnServer("/img_tmp/ref_zw_org.jpg", "/img_tmp/ref_zw.jpg", _basepath); +} + +function GetCoordinates(index, _basepath){ + FileCopyOnServer(ref[index]["name"], "/img_tmp/ref_zw.jpg", _basepath); + + FileDeleteOnServer("/img_tmp/ref_zw_org.jpg", _basepath); + var namezw = ref[index]["name"].replace(".jpg", "_org.jpg"); + FileCopyOnServer(namezw, "/img_tmp/ref_zw_org.jpg", _basepath); + + return ref[index]; +} + +function ParseConfigAlignment(_aktline){ + var akt_ref = 0; + ++_aktline; + + while ((akt_ref < 2) && (_aktline < config_split.length) && (config_split[_aktline][0] != "[")) { + var linesplit = ZerlegeZeile(config_split[_aktline]); + if ((linesplit[0].toUpperCase() == "INITIALMIRROR") && (linesplit.length > 1)) + { + initalrotate["mirror"] = linesplit[1].toUpperCase().localeCompare("TRUE") == 0; + initalrotate["pos_config_mirror"] = _aktline; + } + + if (((linesplit[0].toUpperCase() == "INITALROTATE") || (linesplit[0].toUpperCase() == "INITIALROTATE")) && (linesplit.length > 1)) + { + initalrotate["angle"] = parseInt(linesplit[1]); + initalrotate["pos_config"] = _aktline; + } + if (linesplit.length == 3) + { + ref[akt_ref] = new Object(); + ref[akt_ref]["pos_ref"] = _aktline; + ref[akt_ref]["name"] = linesplit[0]; + ref[akt_ref]["x"] = linesplit[1]; + ref[akt_ref]["y"] = linesplit[2]; + akt_ref++; + } + ++_aktline; + } + return _aktline; +} + +function ParseConfigDigit(_aktline){ + ++_aktline; + digit.length = 0; + + while ((_aktline < config_split.length) && (config_split[_aktline][0] != "[")) { + var linesplit = ZerlegeZeile(config_split[_aktline]); + if (linesplit.length >= 5) + { + zw = new Object(); + zw["pos_ref"] = _aktline; + zw["name"] = linesplit[0]; + zw["x"] = linesplit[1]; + zw["y"] = linesplit[2]; + zw["dx"] = linesplit[3]; + zw["dy"] = linesplit[4]; + zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]); + digit.push(zw); + } + ++_aktline; + } + return _aktline; +} + + +function ParseConfigAnalog(_aktline){ + ++_aktline; + analog.length = 0; + + while ((_aktline < config_split.length) && (config_split[_aktline][0] != "[")) { + var linesplit = ZerlegeZeile(config_split[_aktline]); + if (linesplit.length >= 5) + { + zw = new Object(); + zw["pos_ref"] = _aktline; + zw["name"] = linesplit[0]; + zw["x"] = linesplit[1]; + zw["y"] = linesplit[2]; + zw["dx"] = linesplit[3]; + zw["dy"] = linesplit[4]; + zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]); + analog.push(zw); + } + ++_aktline; + } + return _aktline; +} + + +function getROIInfo(_typeROI){ + if (_typeROI == "[Digits]"){ + targetROI = digit; + } + if (_typeROI == "[Analog]"){ + targetROI = analog; + } + return targetROI.slice(); // Kopie senden, nicht orginal!!! +} + +function SaveROIToConfig(_ROIInfo, _typeROI, _basepath){ + if (_typeROI == "[Digits]"){ + targetROI = digit; + } + if (_typeROI == "[Analog]"){ + targetROI = analog; + } + + // Abstimmen Anzahl ROIs: + var _pos = targetROI[targetROI.length-1]["pos_ref"]; + + for (var i = targetROI.length; i < _ROIInfo.length; ++i){ + var zw = config_split[config_split.length-1]; + config_split.push(zw); + for (var j = config_split.length-2; j > _pos + 1; --j){ + config_split[j] = config_split[j-1]; + } + } + + for (i = targetROI.length-1; i > _ROIInfo.length-1; --i){ + var _zwpos = targetROI[i]["pos_ref"]; + config_split.splice(_zwpos, 1); + } + + var linewrite = 0; + for (i = 0; i < _ROIInfo.length; ++i){ + if (i < targetROI.length){ + linewrite = targetROI[i]["pos_ref"]; + } + else { + linewrite++; + } + config_split[linewrite] = _ROIInfo[i]["name"] + ", " + _ROIInfo[i]["x"] + ", " + _ROIInfo[i]["y"] + ", " + _ROIInfo[i]["dx"] + ", " + _ROIInfo[i]["dy"]; + } + + SaveConfigToServer(_basepath); +} + + +function ParseConfig() { + config_split = config_gesamt.split("\n"); + var aktline = 0; + + while (aktline < config_split.length){ + if (config_split[aktline].trim().toUpperCase() == "[ALIGNMENT]") { + aktline = ParseConfigAlignment(aktline); + continue; + } + if (config_split[aktline].trim().toUpperCase() == "[DIGITS]") { + aktline = ParseConfigDigit(aktline); + continue; + } + + if (config_split[aktline].trim().toUpperCase() == "[ANALOG]") { + aktline = ParseConfigAnalog(aktline); + continue; + } + + aktline++; + } +} + +function getPreRotate(){ + return initalrotate["angle"]; +} + +function setPreRotate(_prerotate){ + initalrotate["angle"] = _prerotate; +} + +function getMirror(){ + if (initalrotate.hasOwnProperty("mirror")) { + return initalrotate["mirror"]; + } + return false; +} + +function setMirror(_mirror){ + initalrotate["mirror"] = _mirror; +} + +function SaveCanvasToImage(_canvas, _filename, _delete = true, _basepath = ""){ + var JPEG_QUALITY=0.8; + var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY); + var rtn = dataURLtoBlob(dataUrl); + + if (_delete) { + FileDeleteOnServer(_filename, _basepath); + } + + FileSendContent(rtn, _filename, _basepath); +} + +function SaveConfigToServer(_basepath){ + // leere Zeilen am Ende löschen + var zw = config_split.length - 1; + while (config_split[zw] == "") { + config_split.pop(); + } + + var config_gesamt = ""; + for (var i = 0; i < config_split.length; ++i) + { + config_gesamt = config_gesamt + config_split[i] + "\n"; + } + + FileDeleteOnServer("/config/config.ini", _basepath); + + FileSendContent(config_gesamt, "/config/config.ini", _basepath); +} + +function UpdateConfigFileReferenceChange(_basepath){ + for (var _index = 0; _index < ref.length; ++_index){ + var zeile = ref[_index]["name"] + " " + ref[_index]["x"] + ", " + ref[_index]["y"]; + var _pos = ref[_index]["pos_ref"]; + config_split[_pos] = zeile; + } + + zeile = "InitialRotate = " + initalrotate["angle"]; + var _pos = initalrotate["pos_config"]; + config_split[_pos] = zeile; + + var mirror = false; + if (initalrotate.hasOwnProperty("mirror")) { + mirror = initalrotate["mirror"]; + } + var mirror_pos = -1; + if (initalrotate.hasOwnProperty("pos_config_mirror")) { + mirror_pos = initalrotate["pos_config_mirror"]; + } + if (mirror_pos > -1) { + if (mirror) { + config_split[mirror_pos] = "InitialMirror = True"; + } + else { + config_split[mirror_pos] = "InitialMirror = False"; + } + } + else { + if (mirror) { // neue Zeile muss an der richtigen Stelle eingefügt werden - hier direct nach [Alignment] + var aktline = 0; + + while (aktline < config_split.length){ + if (config_split[aktline].trim() == "[Alignment]") { + break; + } + aktline++ + } + + // fuege neue Zeile in config_split ein + var zw = config_split[config_split.length-1]; + config_split.push(zw); + for (var j = config_split.length-2; j > aktline + 1; --j){ + config_split[j] = config_split[j-1]; + } + + config_split[aktline + 1] = "InitialMirror = True" + } + } + + SaveConfigToServer(_basepath); +} + +function UpdateConfig(zw, _index, _enhance, _basepath){ + var zeile = zw["name"] + " " + zw["x"] + ", " + zw["y"]; + var _pos = ref[_index]["pos_ref"]; + config_split[_pos] = zeile; + + SaveConfigToServer(_basepath); + + var namezw = zw["name"]; + FileCopyOnServer("/img_tmp/ref_zw.jpg", namezw, _basepath); + var namezw = zw["name"].replace(".jpg", "_org.jpg"); + FileCopyOnServer("/img_tmp/ref_zw_org.jpg", namezw, _basepath); +} + +function MakeContrastImageZW(zw, _enhance, _basepath){ + url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=/img_tmp/ref_zw.jpg" + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; + if (_enhance == true){ + url = url + "&enhance=true"; + } + + var xhttp = new XMLHttpRequest(); + try { + xhttp.open("GET", url, false); + xhttp.send(); } + catch (error) + { +// alert("Deleting Config.ini failed"); + } +} + +function createReader(file) { + var image = new Image(); + reader.onload = function(evt) { + var image = new Image(); + image.onload = function(evt) { + var width = this.width; + var height = this.height; + alert (width); // will produce something like 198 + }; + image.src = evt.target.result; + }; + reader.readAsDataURL(file); + } + +function GetReferenceSize(name){ + img = new Image(); + var xhttp = new XMLHttpRequest(); + + url = "http://192.168.178.22/fileserver" + name; + xhttp.open("GET", url, false); + xhttp.send(); + + var response = xhttp.responseText; + var binary = "" + + for (var responseText = xhttp.responseText, responseTextLen = responseText.length, binary = "", i = 0; i < responseTextLen; ++i) { + binary += String.fromCharCode(responseText.charCodeAt(i) & 255) + } + img.src = 'data:image/jpeg;base64,'+ window.btoa(binary); + + return [img.width, img.height]; +} + + +function ZerlegeZeile(input) + { + var Output = Array(0); + delimiter = " =,"; + + input = trim(input, delimiter); + var pos = findDelimiterPos(input, delimiter); + var token; + while (pos > -1) { + token = input.substr(0, pos); + token = trim(token, delimiter); + Output.push(token); + input = input.substr(pos+1, input.length); + input = trim(input, delimiter); + pos = findDelimiterPos(input, delimiter); + } + Output.push(input); + + return Output; + + } + +function findDelimiterPos(input, delimiter) + { + var pos = -1; + var zw; + var akt_del; + + for (var anz = 0; anz < delimiter.length; ++anz) + { + akt_del = delimiter[anz]; + zw = input.indexOf(akt_del); + if (zw > -1) + { + if (pos > -1) + { + if (zw < pos) + pos = zw; + } + else + pos = zw; + } + } + return pos; + } + + + +function trim(istring, adddelimiter) + { + while ((istring.length > 0) && (adddelimiter.indexOf(istring[0]) >= 0)){ + istring = istring.substr(1, istring.length-1); + } + + while ((istring.length > 0) && (adddelimiter.indexOf(istring[istring.length-1]) >= 0)){ + istring = istring.substr(0, istring.length-1); + } + + return istring; + } + + + +function loadConfig(_basepath) { + var xhttp = new XMLHttpRequest(); + try { + url = _basepath + '/fileserver/config/config.ini'; + xhttp.open("GET", url, false); + xhttp.send(); + config_gesamt = xhttp.responseText; + } + catch (error) + { + // alert("Deleting Config.ini failed"); + } +} + +function getConfig() { + return config_gesamt; + } + + + +function dataURLtoBlob(dataurl) { + var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); + while(n--){ + u8arr[n] = bstr.charCodeAt(n); + } + return new Blob([u8arr], {type:mime}); + } + +function FileCopyOnServer(_source, _target, _basepath = ""){ + url = _basepath + "/editflow.html?task=copy&in=" + _source + "&out=" + _target; + var xhttp = new XMLHttpRequest(); + try { + xhttp.open("GET", url, false); + xhttp.send(); } + catch (error) + { +// alert("Deleting Config.ini failed"); + } +} + +function FileDeleteOnServer(_filename, _basepath = ""){ + var xhttp = new XMLHttpRequest(); + var okay = false; + + xhttp.onreadystatechange = function() { + if (xhttp.readyState == 4) { + if (xhttp.status == 200) { + okay = true; + } else if (xhttp.status == 0) { +// alert("Server closed the connection on delete abruptly!"); +// location.reload() + } else { +// alert(xhttp.status + " Error!\n" + xhttp.responseText); +// location.reload() + } + } + }; + try { + var url = _basepath + "/delete" + _filename; + xhttp.open("POST", url, false); + xhttp.send(); + } + catch (error) + { +// alert("Deleting Config.ini failed"); + } + + return okay; +} + +function FileSendContent(_content, _filename, _basepath = ""){ + var xhttp = new XMLHttpRequest(); + var okay = false; + + xhttp.onreadystatechange = function() { + if (xhttp.readyState == 4) { + if (xhttp.status == 200) { + okay = true; + } else if (xhttp.status == 0) { + alert("Server closed the connection abruptly!"); + } else { + alert(xhttp.status + " Error!\n" + xhttp.responseText); + } + } + }; + + try { + upload_path = _basepath + "/upload" + _filename; + xhttp.open("POST", upload_path, false); + xhttp.send(_content); + } + catch (error) + { +// alert("Deleting Config.ini failed"); + } + return okay; +} + +function SaveReferenceImage(_id_canvas, _filename, _doDelete, _basepath = ""){ + if (_doDelete){ + FileDeleteOnServer(_filename, _basepath); + } + + var canvas = document.getElementById(_id_canvas); + var JPEG_QUALITY=0.8; + var dataUrl = canvas.toDataURL('image/jpeg', JPEG_QUALITY); + var rtn = dataURLtoBlob(dataUrl); + if (!FileSendContent(rtn, _filename, _basepath)){ + alert("Error on saving reference image (" + _filename + ")!\nPlease retry."); + location.reload(); + }; +}