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

added a new URI /log to get last 16kBytes of the current logfile

CaCO3 3 лет назад
Родитель
Сommit
d07aa2a72d
1 измененных файлов с 54 добавлено и 11 удалено
  1. 54 11
      code/components/jomjol_fileserver_ota/server_file.cpp

+ 54 - 11
code/components/jomjol_fileserver_ota/server_file.cpp

@@ -60,6 +60,9 @@ static const char *TAG = "server_file";
 /* Scratch buffer size */
 #define SCRATCH_BUFSIZE  4096 
 
+/* Size of partial log file to return */
+#define LOGFILE_LAST_PART_BYTES SCRATCH_BUFSIZE * 4
+
 struct file_server_data {
     /* Base path of file storage */
     char base_path[ESP_VFS_PATH_MAX + 1];
@@ -80,6 +83,9 @@ using namespace std;
 string SUFFIX_ZW = "_0xge";
 
 
+static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file);
+
+
 esp_err_t get_numbers_file_handler(httpd_req_t *req)
 {
     std::string ret = tfliteflow.getNumbersName();
@@ -320,20 +326,29 @@ 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)
+static esp_err_t logfileact_get_full_handler(httpd_req_t *req) {
+    return send_logfile(req, true);
+}
+
+
+static esp_err_t logfileact_get_last_part_handler(httpd_req_t *req) {
+    return send_logfile(req, false);
+}
+
+
+static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
 {
-    LogFile.WriteToFile(ESP_LOG_DEBUG, "logfileact_get_handler");
+    LogFile.WriteToFile(ESP_LOG_DEBUG, "log_get_last_part_handler");
     char filepath[FILE_PATH_MAX];
     FILE *fd = NULL;
     //struct stat file_stat;
     ESP_LOGD(TAG, "uri: %s", req->uri);
 
-    const char* filename = "log_current.txt"; 
-
-    ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
+    const char* filename; 
 
     std::string currentfilename = LogFile.GetCurrentFileName();
 
+    ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
 
     fd = OpenFileAndWait(currentfilename.c_str(), "r");
     if (!fd) {
@@ -348,6 +363,30 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
 //    ESP_LOGI(TAG_FILESERVER, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
     set_content_type_from_file(req, filename);
 
+    if (!send_full_file) { // Send only last part of file
+        /* Adapted from https://www.geeksforgeeks.org/implement-your-own-tail-read-last-n-lines-of-a-huge-file/ */
+        if (fseek(fd, 0, SEEK_END)) {
+            ESP_LOGE(TAG_FILESERVER, "Failed to get to end of file!");
+            return ESP_FAIL;
+        }
+        else {
+            long pos = ftell(fd); // Number of bytes in the file
+            ESP_LOGI(TAG_FILESERVER, "File contains %ld bytes", pos);
+
+            if (fseek(fd, pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos), SEEK_SET)) { // Go LOGFILE_LAST_PART_BYTES bytes back from EOF
+                ESP_LOGE(TAG_FILESERVER, "Failed to go back %ld bytes within the file!", std::min((long)LOGFILE_LAST_PART_BYTES, pos));
+                return ESP_FAIL;
+            }
+        }
+
+        /* Find end of line */
+        while (1) {
+            if (fgetc(fd) == '\n') {
+                break;
+            }
+        }
+    }
+
     /* Retrieve the pointer to scratch buffer for temporary storage */
     char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
     size_t chunksize;
@@ -379,11 +418,6 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
 }
 
 
-
-
-
-
-
 /* Handler to download a file kept on the server */
 static esp_err_t download_get_handler(httpd_req_t *req)
 {
@@ -999,12 +1033,21 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
     httpd_uri_t file_logfileact = {
         .uri       = "/logfileact",  // Match all URIs of type /path/to/file
         .method    = HTTP_GET,
-        .handler   = logfileact_get_handler,
+        .handler   = logfileact_get_full_handler,
         .user_ctx  = server_data    // Pass server data as context
     };
     httpd_register_uri_handler(server, &file_logfileact);
 
 
+    httpd_uri_t file_logfile_last_part_handle = {
+        .uri       = "/log",  // Match all URIs of type /path/to/file
+        .method    = HTTP_GET,
+        .handler   = logfileact_get_last_part_handler,
+        .user_ctx  = server_data    // Pass server data as context
+    };
+    httpd_register_uri_handler(server, &file_logfile_last_part_handle);
+
+
     /* URI handler for uploading files to server */
     httpd_uri_t file_upload = {
         .uri       = "/upload/*",   // Match all URIs of type /upload/path/to/file