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

add new method and finish repo download

There was an out of memory error that was driving me crazy lol. We had over 90k bytes free but still had issues. Turns out, using furi_string_push_back was the issue. Switching to furi_string_cat_str works (for smaller data at least).
jblanked 1 год назад
Родитель
Сommit
212add0ee2
3 измененных файлов с 127 добавлено и 20 удалено
  1. 95 0
      flipper_http/flipper_http.c
  2. 1 0
      flipper_http/flipper_http.h
  3. 31 20
      github/flip_store_github.c

+ 95 - 0
flipper_http/flipper_http.c

@@ -155,6 +155,101 @@ FuriString *flipper_http_load_from_file(char *file_path)
     return str_result;
 }
 
+FuriString *flipper_http_load_from_file_with_limit(char *file_path, size_t limit)
+{
+    // Open the storage record
+    Storage *storage = furi_record_open(RECORD_STORAGE);
+    if (!storage)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to open storage record");
+        return NULL;
+    }
+
+    // Allocate a file handle
+    File *file = storage_file_alloc(storage);
+    if (!file)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate storage file");
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Open the file for reading
+    if (!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING))
+    {
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        FURI_LOG_E(HTTP_TAG, "Failed to open file for reading: %s", file_path);
+        return NULL;
+    }
+
+    if (memmgr_get_free_heap() < limit)
+    {
+        FURI_LOG_E(HTTP_TAG, "Not enough heap to read file.");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Allocate a buffer to hold the read data
+    uint8_t *buffer = (uint8_t *)malloc(limit);
+    if (!buffer)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate buffer");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Allocate a FuriString with preallocated capacity
+    FuriString *str_result = furi_string_alloc();
+    if (!str_result)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate FuriString");
+        free(buffer);
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+    furi_string_reserve(str_result, limit);
+
+    // Read data into the buffer
+    size_t read_count = storage_file_read(file, buffer, limit);
+    if (storage_file_get_error(file) != FSE_OK)
+    {
+        FURI_LOG_E(HTTP_TAG, "Error reading from file.");
+        furi_string_free(str_result);
+        free(buffer);
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+    if (read_count == 0)
+    {
+        FURI_LOG_E(HTTP_TAG, "No data read from file.");
+        furi_string_free(str_result);
+        free(buffer);
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    // Append the entire buffer to FuriString in one operation
+    furi_string_cat_str(str_result, (char *)buffer);
+
+    // Clean up
+    storage_file_close(file);
+    storage_file_free(file);
+    furi_record_close(RECORD_STORAGE);
+    free(buffer);
+    return str_result;
+}
+
 // UART worker thread
 /**
  * @brief      Worker thread to handle UART data asynchronously.

+ 1 - 0
flipper_http/flipper_http.h

@@ -101,6 +101,7 @@ bool flipper_http_append_to_file(
     char *file_path);
 
 FuriString *flipper_http_load_from_file(char *file_path);
+FuriString *flipper_http_load_from_file_with_limit(char *file_path, size_t limit);
 
 // UART worker thread
 /**

+ 31 - 20
github/flip_store_github.c

@@ -9,20 +9,13 @@ bool flip_store_download_github_file(
     const char *repo,
     const char *link)
 {
-    if (!fhttp)
+    if (!fhttp || !filename || !author || !repo || !link)
     {
-        FURI_LOG_E(TAG, "FlipperHTTP is NULL");
+        FURI_LOG_E(TAG, "Invalid arguments.");
         return false;
     }
 
-    // Create the file directory
-    char dir[256];
-    snprintf(dir, sizeof(dir), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/%s/%s/%s", author, repo, filename);
-    snprintf(fhttp->file_path, sizeof(fhttp->file_path), "%s", dir);
-    Storage *storage = furi_record_open(RECORD_STORAGE);
-    storage_common_mkdir(storage, dir);
-    furi_record_close(RECORD_STORAGE);
-
+    snprintf(fhttp->file_path, sizeof(fhttp->file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/%s/%s/%s.txt", author, repo, filename);
     fhttp->state = IDLE;
     fhttp->save_received_data = false;
     fhttp->is_bytes_request = true;
@@ -307,20 +300,15 @@ bool flip_store_install_all_github_files(FlipperHTTP *fhttp, const char *author,
     int count = atoi(furi_string_get_cstr(file_count));
     furi_string_free(file_count);
 
-    bool parse()
-    {
-        return true;
-    }
-
     // install all files
     char file_dir[256]; // /ext/apps_data/flip_store/data/author/repo/file.json
     FURI_LOG_I(TAG, "Installing %d files.", count);
     for (int i = 0; i < count; i++)
     {
         snprintf(file_dir, sizeof(file_dir), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/data/%s/%s/file%d.json", author, repo, i);
-        FURI_LOG_I(TAG, "Loading file %s.", file_dir);
-        FuriString *file = flipper_http_load_from_file(file_dir);
-        if (file == NULL)
+        FURI_LOG_I(TAG, "Loading file %s. Available memory: %d bytes", file_dir, memmgr_get_free_heap());
+        FuriString *file = flipper_http_load_from_file_with_limit(file_dir, 512);
+        if (!file)
         {
             FURI_LOG_E(TAG, "Failed to load file.");
             return false;
@@ -348,8 +336,31 @@ bool flip_store_install_all_github_files(FlipperHTTP *fhttp, const char *author,
             return flip_store_download_github_file(fhttp, furi_string_get_cstr(name), author, repo, furi_string_get_cstr(link));
         }
 
+        bool parse()
+        {
+            // remove .txt from the filename
+            char current_file_path[256];
+            char new_file_path[256];
+            snprintf(current_file_path, sizeof(current_file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/%s/%s/%s.txt", author, repo, furi_string_get_cstr(name));
+            snprintf(new_file_path, sizeof(new_file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_store/%s/%s/%s", author, repo, furi_string_get_cstr(name));
+            Storage *storage = furi_record_open(RECORD_STORAGE);
+            if (!storage_file_exists(storage, current_file_path))
+            {
+                FURI_LOG_E(TAG, "Failed to download file.");
+                furi_record_close(RECORD_STORAGE);
+                return false;
+            }
+            if (storage_common_rename(storage, current_file_path, new_file_path) != FSE_OK)
+            {
+                FURI_LOG_E(TAG, "Failed to rename file.");
+                furi_record_close(RECORD_STORAGE);
+                return false;
+            }
+            furi_record_close(RECORD_STORAGE);
+            return true;
+        }
         // download the file and wait until it is downloaded
-        FURI_LOG_I(TAG, "Downloading file %s.", furi_string_get_cstr(name));
+        FURI_LOG_I(TAG, "Downloading file %s", furi_string_get_cstr(name));
         if (!flipper_http_process_response_async(fhttp, fetch_file, parse))
         {
             FURI_LOG_E(TAG, "Failed to download file.");
@@ -357,7 +368,7 @@ bool flip_store_install_all_github_files(FlipperHTTP *fhttp, const char *author,
             furi_string_free(link);
             return false;
         }
-        FURI_LOG_I(TAG, "Downloaded file %s.", furi_string_get_cstr(name));
+        FURI_LOG_I(TAG, "Downloaded file %s", furi_string_get_cstr(name));
         furi_string_free(name);
         furi_string_free(link);
     }