Просмотр исходного кода

Enhance UI (#1243)

* Temporarily disable data file writing as it can cause crashs, see https://github.com/jomjol/AI-on-the-edge-device/issues/1225

* removed edit function in graph as we don't need that in a release

* .

* improve log viewer

* replaced logfile enable/disable with enum to select log level. At least errors always will be logged (as before)

* .

* .

* colorize log

* scroll down

* improve log reload
CaCO3 3 лет назад
Родитель
Сommit
d2b93a7110

+ 14 - 10
code/components/jomjol_flowcontroll/ClassFlowControll.cpp

@@ -460,13 +460,22 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
         }
         if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
         {
-            if (toUpper(zerlegt[1]) == "TRUE")
+            /* matches esp_log_level_t */
+            if ((toUpper(zerlegt[1]) == "TRUE") || (toUpper(zerlegt[1]) == "2"))
+            {
+                LogFile.setLogLevel(ESP_LOG_WARN);
+            }
+            else if ((toUpper(zerlegt[1]) == "FALSE") || (toUpper(zerlegt[1]) == "0") || (toUpper(zerlegt[1]) == "1"))
+            {
+                LogFile.setLogLevel(ESP_LOG_ERROR);
+            }
+            else if (toUpper(zerlegt[1]) == "3")
             {
-                LogFile.SwitchOnOff(true);
+                LogFile.setLogLevel(ESP_LOG_INFO);
             }
-            if (toUpper(zerlegt[1]) == "FALSE")
+            else if (toUpper(zerlegt[1]) == "4")
             {
-                LogFile.SwitchOnOff(false);
+                LogFile.setLogLevel(ESP_LOG_DEBUG);
             }
         }
         if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
@@ -505,12 +514,7 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
             {
                 SetupModeActive = true;
             }        
-        }      
-
-        if ((toUpper(zerlegt[0]) == "LOGLEVEL") && (zerlegt.size() > 1)) // TODO there seems to be no such parameter in the config, but there is one called "Debug_Logfile_value1"!
-        {
-            LogFile.setLogLevel((esp_log_level_t)(stoi(zerlegt[1]))); // Gets mapped to esp_log_level_t
-        }      
+        }
     }
 
     AutoIntervalShared = AutoIntervall;

+ 36 - 9
code/components/jomjol_logfile/ClassLogFile.cpp

@@ -80,9 +80,10 @@ void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::s
     FILE* pFile;
     std::string zwtime;
 
-    if (!doLogFile){
+    // TODO add separate parameter to disable write of data. 
+    /*if (!doLogFile){
         return;
-    }
+    }*/
 
     ESP_LOGD(TAG, "Datalogfile: %s", logpath.c_str());
     pFile = fopen(logpath.c_str(), "a+");
@@ -121,7 +122,7 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level,
     std::string zwtime;
     std::string logline = "";
 
-    if (!doLogFile && level != ESP_LOG_ERROR){ // Only write to file if logfile is enabled or its an error message
+    if (level > loglevel) {// Only write to file if loglevel is below threshold
         return;
     }
 
@@ -147,9 +148,6 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level,
 
         std::string loglevelString; 
         switch(level) {
-            case  ESP_LOG_NONE:
-                loglevelString = "NONE";
-                break;
             case  ESP_LOG_ERROR:
                 loglevelString = "ERR";
                 break;
@@ -165,6 +163,7 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level,
             case  ESP_LOG_VERBOSE:
                 loglevelString = "VER";
                 break;
+            case  ESP_LOG_NONE:
             default:
                 loglevelString = "NONE";
                 break;
@@ -178,8 +177,37 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level,
     }
 }
 
-void ClassLogFile::SwitchOnOff(bool _doLogFile){
-    doLogFile = _doLogFile;
+void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
+    loglevel = _logLevel;
+
+    std::string levelText;
+
+    switch(_logLevel) {            
+        case ESP_LOG_WARN:
+            levelText = "WARNING";
+            break;
+            
+        case ESP_LOG_INFO:
+            levelText = "INFO";
+            break;
+            
+        case ESP_LOG_DEBUG:
+            levelText = "DEBUG";
+            break;
+        case ESP_LOG_ERROR:
+        default:
+            levelText = "ERROR";
+            break;
+    }
+
+    ESP_LOGI(TAG, "Logfile Log Level set to %s", levelText.c_str());
+
+    /*
+    LogFile.WriteToFile(ESP_LOG_ERROR, "Test");
+    LogFile.WriteToFile(ESP_LOG_WARN, "Test");
+    LogFile.WriteToFile(ESP_LOG_INFO, "Test");
+    LogFile.WriteToFile(ESP_LOG_DEBUG, "Test");
+    */
 };
 
 void ClassLogFile::SetRetention(unsigned short _retentionInDays){
@@ -325,7 +353,6 @@ ClassLogFile::ClassLogFile(std::string _logroot, std::string _logfile, std::stri
     logfile =  _logfile;
     datafile = _datafile;
     dataroot = _logdatapath;
-    doLogFile = true;
     retentionInDays = 10;
     loglevel = ESP_LOG_INFO;
     MakeDir("/sdcard/log/data");

+ 1 - 4
code/components/jomjol_logfile/ClassLogFile.h

@@ -10,7 +10,6 @@ private:
     std::string logfile;
     std::string dataroot;
     std::string datafile;
-    bool doLogFile;
     unsigned short retentionInDays;
     esp_log_level_t loglevel;
 public:
@@ -18,11 +17,9 @@ public:
 
     std::string getESPHeapInfo();
 
-    void setLogLevel(esp_log_level_t i){loglevel = i;};
-
     void WriteHeapInfo(std::string _id);
 
-    void SwitchOnOff(bool _doLogFile);
+    void setLogLevel(esp_log_level_t _logLevel);
     void SetRetention(unsigned short _retentionInDays);
 
     void WriteToFile(esp_log_level_t level, std::string info, bool _time = true);

+ 10 - 8
sd-card/html/edit_config_param.html

@@ -745,7 +745,7 @@ textarea {
 			<td colspan="3" style="padding-left: 20px;">
 				<h4><input type="checkbox" id="Category_GPIO_enabled" value="1"  onclick='UpdateAfterCategoryCheck()' unchecked > 
 				    <label for=Category_GPIO_enabled>GPIO Settings
-					<span class="GPIO_Item" > - Enabling GPIO handler, disable by default integrated flash light. Please enable it with GPIO4 (internal flash LED) settings or GPIO12 (external LED).</span></label>
+					<span class="GPIO_Item" > - Enabling GPIO handler, disable by default integrated flash light.<br>Please enable it with GPIO4 (internal flash LED) settings or GPIO12 (external LED).</span></label>
 				</h4>	
 			</td>
 		</tr> 	
@@ -1249,18 +1249,20 @@ textarea {
 		<tr>
 			<td class="indent1">
 				<input type="checkbox" id="Debug_Logfile_enabled" value="1"  onclick = 'InvertEnableItem("Debug", "Logfile")' unchecked >
-				<label for=Debug_Logfile_enabled><class id="Debug_Logfile_text" style="color:black;">Logfile</class></label>
+				<label for=Debug_Logfile_enabled><class id="Debug_Logfile_text" style="color:black;">Logfile Log Level</class></label>
 			</td>
 			<td>
 				<select id="Debug_Logfile_value1">
-					<option value="true" selected>true</option>
-					<option value="false" >false</option>
+					<option value="1" selected>ERROR</option> <!-- matches esp_log_level_t -->
+					<option value="2">WARNING</option>
+					<option value="3">INFO</option>
+					<option value="4">DEBUG</option>
 				</select>
 			</td>
 			<td class="description">
-				Turn on/off the extended logging
+				Set the level of the logging to the SD-Card.<br><b>Warning:</b> DEBUG or INFO might damage the SD-Card if enabled longterm due to excessive writes to the SD-Card!
 			</td>
-		</tr>
+		</tr> 		
 		<tr>
 			<td class="indent1">
 				<input type="checkbox" id="Debug_LogfileRetentionInDays_enabled" value="1"  onclick = 'InvertEnableItem("Debug", "LogfileRetentionInDays")' unchecked >
@@ -1431,7 +1433,7 @@ function WriteParameter(_param, _category, _cat, _name, _optional, _number = -1)
 				}
 				if (!_isFound)
 				{
-					_zw_txt = "In the selectd field the value '" + textToFind + "' in the parameter '";
+					_zw_txt = "In the selected field the value '" + textToFind + "' in the parameter '";
 					_zw_txt = _zw_txt + _cat + "' in the field '" + _name + "' is invalid.\nPLEASE CHECK BEFORE SAVING!";
 					alert(_zw_txt);
 				}
@@ -1472,7 +1474,7 @@ function WriteParameter(_param, _category, _cat, _name, _optional, _number = -1)
 				}
 				if (!_isFound)
 				{
-					_zw_txt = "In the selectd field the value '" + textToFind + "' in the section '";
+					_zw_txt = "In the selected field the value '" + textToFind + "' in the section '";
 					_zw_txt = _zw_txt + _cat + "' in the field '" + _name + "' is invalid.\nPLEASE CHECK BEFORE SAVING!";
 					alert(_zw_txt);
 				}

+ 15 - 19
sd-card/html/graph.html

@@ -1,4 +1,3 @@
-
 <html>
     <head>
     <script src='https://cdn.plot.ly/plotly-2.14.0.min.js'></script>
@@ -18,22 +17,21 @@
       var el = document.getElementById('cnsl');
       el && eval(el.value);
     }
-
-
     </script>
+
     </head>
     <body>
     <div id='chart'></div>
-    <select id="datafiles" onchange="run();"></select>
-    <select id="numbers" onchange="run();"></select>
-    <select id="datatype" onchange="run();">
-        <option value="3">Value</option>
-        <option value="4">PreValue</option>
-        <option value="5">Change-Rate</option>
-        <option value="6">Change-Absolut</option>
-      </select>
-
-    <button onclick="document.getElementById('editor').hidden = false; this.hidden = true;" >Editor</button>
+        <select id="datafiles" onchange="run();"></select>
+        <select id="numbers" onchange="run();"></select>
+        <select id="datatype" onchange="run();">
+            <option value="3">Value</option>
+            <option value="4">PreValue</option>
+            <option value="5">Change-Rate</option>
+            <option value="6">Change-Absolut</option>
+        </select>
+
+  <!-- <button onclick="document.getElementById('editor').hidden = false; this.hidden = true;" >Editor</button> -->
     <div id='editor' hidden='true'>
     <textarea id="cnsl">
 datefile = document.getElementById("datafiles").value;
@@ -84,9 +82,9 @@ alert("test");
 </textarea><br />
 <button onclick="run();">run</button>
 </div>
-<script>
 
-function WriteModelFiles()
+<script>
+    function WriteModelFiles()
     {
         list_data = getDATAList();
 
@@ -127,9 +125,7 @@ function WriteModelFiles()
     WriteModelFiles();
     WriteNumbers();
 
-
-
-run();
+    run();
 </script>
 </body>
-</html>
+</html>

+ 1 - 1
sd-card/html/index.html

@@ -68,7 +68,7 @@
         <ul class="submenu">
             <li><a href="#" onclick="loadPage('backup.html');">Backup/Restore</a></li>
             <li><a href="#" onclick="loadPage('ota_page.html');">OTA Update</a></li>
-            <li><a href="#" onclick="loadPage('fileserver/log/message/?readonly=true');">Log Viewer</a></li>
+            <li><a href="#" onclick="loadPage('log.html');">Log Viewer</a></li>
             <li><a href="#" onclick="loadPage('reboot_page.html');">Reboot</a></li>
             <li><a href="#" onclick="loadPage('info.html');">Info</a></li>
         </ul>

+ 100 - 0
sd-card/html/log.html

@@ -0,0 +1,100 @@
+<html>
+    <head>
+        <style>
+            html,
+            body {
+                height: 100%;
+                margin: 2px;
+            }
+
+            .box {
+                display: flex;
+                flex-flow: column;
+                height: 100%;
+            }
+
+            .box .row.header {
+                flex: 0 1 auto;
+            }
+
+            .box .row.content {
+                flex: 1 1 auto;
+            }
+
+            .box .row.footer {
+                flex: 0 1 auto;
+            }
+
+            #log {
+                font-family: 'Courier New', Courier, monospace;
+                font-size: small;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="box">
+            <div class="row header">
+                <button onClick="reload();">Reload</button>
+                <button onClick="window.open('logfileact');">Show full log</button>
+                <button onClick="window.location.href = 'fileserver/log/message/'">Show older log files</button>
+            </div>
+            <div class="row content" id="log"><br><br><br><b>Loading Logfile, please wait...</b></div>
+            <div class="row footer">
+                <button onClick="reload();">Reload</button>
+                <button onClick="window.open('logfileact');">Show full log</button>
+                <button onClick="window.location.href = 'fileserver/log/message/'">Show older log files</button>
+            </div>
+          </div>
+    </body>
+
+    <script>  
+        function reload() {
+          //  document.getElementById('log').innerHTML += "<br><b>Reloading...<b><br><br>";
+            document.getElementById('log').innerHTML += "<b>Reloading...</b>";
+            window.scrollBy(0,document.body.scrollHeight);
+            funcRequest('log');
+        } 
+
+
+        function processLogLine(line, index, arr) {
+            if (line.includes("&lt;WRN&gt;")) {
+                arr[index] = "<span style=\"color:#e83c00\">" + line + "</span>";
+            }
+            else if (line.includes("&lt;ERR&gt;")) {
+                arr[index] = "<span style=\"color:red\"><b>" + line + "</b></span>";
+            }
+            else if (line.includes("&lt;DBG&gt;")) {
+                arr[index] = "<span style=\"color:gray\">" + line + "</span>";
+            }
+            
+            arr[index] += "<br>";
+        }
+
+        async function funcRequest(url){
+            await fetch(url)
+            .then((res) => {
+                if (!res.ok) {
+                    document.getElementById("log").innerHTML = "HTTP error " + res.status;
+                }
+
+                return res.text();
+            })
+            .then((log) => {
+                log = log.replace(/</g, "&lt;").replace(/>/g, "&gt;");
+                logArr = log.split("\n");
+                logArr.forEach(processLogLine);
+
+                document.getElementById('log').innerHTML = "<br>" + logArr.join("\n") + "&nbsp;";
+
+                window.scrollBy(0,document.body.scrollHeight);
+
+            })
+            .catch((err) => {
+                document.getElementById("log").innerHTML = err;
+            });
+        }
+
+        funcRequest('log');
+
+    </script>
+</html>