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

Merge flip_library from https://github.com/jblanked/FlipLibrary

Willy-JL 1 год назад
Родитель
Сommit
6b64eabdbe

BIN
flip_library/.DS_Store


+ 0 - 21
flip_library/LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2024 jblanked
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 5 - 0
flip_library/README.md

@@ -34,3 +34,8 @@ The app automatically allocates necessary resources and initializes settings. If
    - Visit **Random Facts** to read interesting trivia.
    - Configure **WiFi settings** if network-related features are required in the future.
    - Check the **About** section to learn more about the app.
+
+# Known Bugs
+
+1. **Screen Delay**: Occasionally, the Defition or Random Facts screen may get stuck on "Loading".
+   - If it takes longer than 10 seconds, restart your Flipper Zero.

+ 2 - 5
flip_library/flip_library_i.h → flip_library/alloc/flip_library_alloc.c

@@ -1,8 +1,7 @@
-#ifndef FLIP_LIBRARY_I_H
-#define FLIP_LIBRARY_I_H
+#include "alloc/flip_library_alloc.h"
 
 // Function to allocate resources for the FlipLibraryApp
-static FlipLibraryApp* flip_library_app_alloc() {
+FlipLibraryApp* flip_library_app_alloc() {
     FlipLibraryApp* app = (FlipLibraryApp*)malloc(sizeof(FlipLibraryApp));
 
     Gui* gui = furi_record_open(RECORD_GUI);
@@ -251,5 +250,3 @@ static FlipLibraryApp* flip_library_app_alloc() {
 
     return app;
 }
-
-#endif // FLIP_LIBRARY_I_H

+ 10 - 0
flip_library/alloc/flip_library_alloc.h

@@ -0,0 +1,10 @@
+#ifndef FLIP_LIBRARY_I_H
+#define FLIP_LIBRARY_I_H
+
+#include <flip_library.h>
+#include <callback/flip_library_callback.h>
+
+// Function to allocate resources for the FlipLibraryApp
+FlipLibraryApp* flip_library_app_alloc();
+
+#endif // FLIP_LIBRARY_I_H

+ 6 - 9
flip_library/app.c

@@ -1,8 +1,5 @@
-#include <flip_library_e.h>
-#include <flip_library_storage.h>
-#include <flip_library_callback.h>
-#include <flip_library_i.h>
-#include <flip_library_free.h>
+#include <flip_library.h>
+#include <alloc/flip_library_alloc.h>
 
 // Entry point for the FlipLibrary application
 int32_t flip_library_app(void* p) {
@@ -10,8 +7,8 @@ int32_t flip_library_app(void* p) {
     UNUSED(p);
 
     // Initialize the FlipLibrary application
-    FlipLibraryApp* app = flip_library_app_alloc();
-    if(!app) {
+    app_instance = flip_library_app_alloc();
+    if(!app_instance) {
         FURI_LOG_E(TAG, "Failed to allocate FlipLibraryApp");
         return -1;
     }
@@ -22,10 +19,10 @@ int32_t flip_library_app(void* p) {
     }
 
     // Run the view dispatcher
-    view_dispatcher_run(app->view_dispatcher);
+    view_dispatcher_run(app_instance->view_dispatcher);
 
     // Free the resources used by the FlipLibrary application
-    flip_library_app_free(app);
+    flip_library_app_free(app_instance);
 
     // Return 0 to indicate success
     return 0;

+ 1 - 1
flip_library/application.fam

@@ -10,5 +10,5 @@ App(
     fap_description="Dictionary, random facts, and more.",
     fap_author="JBlanked",
     fap_weburl="https://github.com/jblanked/FlipLibrary",
-    fap_version="1.1",
+    fap_version="1.2",
 )

BIN
flip_library/assets/01-main.png


BIN
flip_library/assets/02-random-facts.png


+ 23 - 25
flip_library/flip_library_callback.h → flip_library/callback/flip_library_callback.c

@@ -1,13 +1,9 @@
-#ifndef FLIP_LIBRARY_CALLBACK_H
-#define FLIP_LIBRARY_CALLBACK_H
-static uint32_t random_facts_index = 0;
-static bool sent_random_fact_request = false;
-static bool random_fact_request_success = false;
-static bool random_fact_request_success_all = false;
+#include <callback/flip_library_callback.h>
+uint32_t random_facts_index = 0;
+bool sent_random_fact_request = false;
+bool random_fact_request_success = false;
+bool random_fact_request_success_all = false;
 char* random_fact = NULL;
-static FlipLibraryApp* app_instance = NULL;
-
-#define MAX_TOKENS 512 // Adjust based on expected JSON size
 
 // Parse JSON to find the "text" key
 char* flip_library_parse_random_fact() {
@@ -19,7 +15,7 @@ char* flip_library_parse_cat_fact() {
 }
 
 char* flip_library_parse_dog_fact() {
-    return get_json_array_value("facts", 0, fhttp.last_response, 128);
+    return get_json_array_value("facts", 0, fhttp.last_response, 256);
 }
 
 char* flip_library_parse_quote() {
@@ -45,7 +41,7 @@ char* flip_library_parse_dictionary() {
     return get_json_value("definition", fhttp.last_response, 16);
 }
 
-static void flip_library_request_error(Canvas* canvas) {
+void flip_library_request_error(Canvas* canvas) {
     if(fhttp.last_response == NULL) {
         if(fhttp.last_response != NULL) {
             if(strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") !=
@@ -78,7 +74,7 @@ static void flip_library_request_error(Canvas* canvas) {
     }
 }
 
-static void flip_library_draw_fact(char* message, Widget** widget) {
+void flip_library_draw_fact(char* message, Widget** widget) {
     if(app_instance == NULL) {
         FURI_LOG_E(TAG, "App instance is NULL");
         return;
@@ -138,7 +134,7 @@ static void flip_library_draw_fact(char* message, Widget** widget) {
 }
 
 // Callback for drawing the main screen
-static void view_draw_callback_random_facts(Canvas* canvas, void* model) {
+void view_draw_callback_random_facts(Canvas* canvas, void* model) {
     if(!canvas || !app_instance) {
         return;
     }
@@ -245,6 +241,7 @@ static void view_draw_callback_random_facts(Canvas* canvas, void* model) {
             if(!random_fact_request_success) {
                 FURI_LOG_E(TAG, "Failed to send request");
                 flip_library_request_error(canvas);
+                fhttp.state = ISSUE;
                 return;
             }
             fhttp.state = RECEIVING;
@@ -400,6 +397,7 @@ static void view_draw_callback_random_facts(Canvas* canvas, void* model) {
                 flipper_http_get_request("https://uselessfacts.jsph.pl/api/v2/facts/random");
             if(!random_fact_request_success) {
                 FURI_LOG_E(TAG, "Failed to send request");
+                fhttp.state = ISSUE;
                 return;
             }
             fhttp.state = RECEIVING;
@@ -472,7 +470,7 @@ static void view_draw_callback_random_facts(Canvas* canvas, void* model) {
     }
 }
 
-static void view_draw_callback_dictionary_run(Canvas* canvas, void* model) {
+void view_draw_callback_dictionary_run(Canvas* canvas, void* model) {
     if(!canvas || !app_instance || app_instance->uart_text_input_buffer_dictionary == NULL) {
         return;
     }
@@ -509,6 +507,8 @@ static void view_draw_callback_dictionary_run(Canvas* canvas, void* model) {
             payload);
         if(!random_fact_request_success) {
             FURI_LOG_E(TAG, "Failed to send request");
+            flip_library_request_error(canvas);
+            fhttp.state = ISSUE;
             return;
         }
         fhttp.state = RECEIVING;
@@ -603,7 +603,7 @@ bool view_input_callback_random_facts(InputEvent* event, void* context) {
     return false;
 }
 
-static void callback_submenu_choices(void* context, uint32_t index) {
+void callback_submenu_choices(void* context, uint32_t index) {
     FlipLibraryApp* app = (FlipLibraryApp*)context;
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
@@ -654,7 +654,7 @@ static void callback_submenu_choices(void* context, uint32_t index) {
     }
 }
 
-static void text_updated_ssid(void* context) {
+void text_updated_ssid(void* context) {
     FlipLibraryApp* app = (FlipLibraryApp*)context;
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
@@ -692,7 +692,7 @@ static void text_updated_ssid(void* context) {
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
 }
 
-static void text_updated_password(void* context) {
+void text_updated_password(void* context) {
     FlipLibraryApp* app = (FlipLibraryApp*)context;
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
@@ -730,7 +730,7 @@ static void text_updated_password(void* context) {
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
 }
 
-static void text_updated_dictionary(void* context) {
+void text_updated_dictionary(void* context) {
     FlipLibraryApp* app = (FlipLibraryApp*)context;
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
@@ -750,7 +750,7 @@ static void text_updated_dictionary(void* context) {
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewDictionaryRun);
 }
 
-static uint32_t callback_to_submenu(void* context) {
+uint32_t callback_to_submenu(void* context) {
     if(!context) {
         FURI_LOG_E(TAG, "Context is NULL");
         return VIEW_NONE;
@@ -764,7 +764,7 @@ static uint32_t callback_to_submenu(void* context) {
     return FlipLibraryViewSubmenuMain;
 }
 
-static uint32_t callback_to_wifi_settings(void* context) {
+uint32_t callback_to_wifi_settings(void* context) {
     if(!context) {
         FURI_LOG_E(TAG, "Context is NULL");
         return VIEW_NONE;
@@ -773,7 +773,7 @@ static uint32_t callback_to_wifi_settings(void* context) {
     return FlipLibraryViewSettings;
 }
 
-static uint32_t callback_to_random_facts(void* context) {
+uint32_t callback_to_random_facts(void* context) {
     if(!context) {
         FURI_LOG_E(TAG, "Context is NULL");
         return VIEW_NONE;
@@ -782,7 +782,7 @@ static uint32_t callback_to_random_facts(void* context) {
     return FlipLibraryViewRandomFacts;
 }
 
-static void settings_item_selected(void* context, uint32_t index) {
+void settings_item_selected(void* context, uint32_t index) {
     FlipLibraryApp* app = (FlipLibraryApp*)context;
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
@@ -806,7 +806,7 @@ static void settings_item_selected(void* context, uint32_t index) {
  * @param context The context - unused
  * @return next view id (VIEW_NONE to exit the app)
  */
-static uint32_t callback_exit_app(void* context) {
+uint32_t callback_exit_app(void* context) {
     // Exit the application
     if(!context) {
         FURI_LOG_E(TAG, "Context is NULL");
@@ -815,5 +815,3 @@ static uint32_t callback_exit_app(void* context) {
     UNUSED(context);
     return VIEW_NONE; // Return VIEW_NONE to exit the app
 }
-
-#endif // FLIP_LIBRARY_CALLBACK_H

+ 60 - 0
flip_library/callback/flip_library_callback.h

@@ -0,0 +1,60 @@
+#ifndef FLIP_LIBRARY_CALLBACK_H
+#define FLIP_LIBRARY_CALLBACK_H
+#include <flip_library.h>
+#include <flip_storage/flip_library_storage.h>
+
+#define MAX_TOKENS 512 // Adjust based on expected JSON size
+
+extern uint32_t random_facts_index;
+extern bool sent_random_fact_request;
+extern bool random_fact_request_success;
+extern bool random_fact_request_success_all;
+extern char* random_fact;
+
+// Parse JSON to find the "text" key
+char* flip_library_parse_random_fact();
+
+char* flip_library_parse_cat_fact();
+
+char* flip_library_parse_dog_fact();
+
+char* flip_library_parse_quote();
+
+char* flip_library_parse_dictionary();
+
+void flip_library_request_error(Canvas* canvas);
+
+void flip_library_draw_fact(char* message, Widget** widget);
+
+// Callback for drawing the main screen
+void view_draw_callback_random_facts(Canvas* canvas, void* model);
+
+void view_draw_callback_dictionary_run(Canvas* canvas, void* model);
+
+// Input callback for the view (async input handling)
+bool view_input_callback_random_facts(InputEvent* event, void* context);
+
+void callback_submenu_choices(void* context, uint32_t index);
+
+void text_updated_ssid(void* context);
+
+void text_updated_password(void* context);
+
+void text_updated_dictionary(void* context);
+
+uint32_t callback_to_submenu(void* context);
+
+uint32_t callback_to_wifi_settings(void* context);
+
+uint32_t callback_to_random_facts(void* context);
+
+void settings_item_selected(void* context, uint32_t index);
+
+/**
+ * @brief Navigation callback for exiting the application
+ * @param context The context - unused
+ * @return next view id (VIEW_NONE to exit the app)
+ */
+uint32_t callback_exit_app(void* context);
+
+#endif // FLIP_LIBRARY_CALLBACK_H

+ 1 - 23
flip_library/easy_flipper.h → flip_library/easy_flipper/easy_flipper.c

@@ -1,24 +1,4 @@
-#ifndef EASY_FLIPPER_H
-#define EASY_FLIPPER_H
-
-#include <malloc.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <gui/view.h>
-#include <gui/modules/submenu.h>
-#include <gui/view_dispatcher.h>
-#include <gui/modules/menu.h>
-#include <gui/modules/submenu.h>
-#include <gui/modules/widget.h>
-#include <gui/modules/text_input.h>
-#include <gui/modules/text_box.h>
-#include <gui/modules/variable_item_list.h>
-#include <gui/modules/dialog_ex.h>
-#include <gui/modules/popup.h>
-#include <gui/modules/loading.h>
-
-#define EASY_TAG "EasyFlipper"
+#include <easy_flipper/easy_flipper.h>
 
 /**
  * @brief Navigation callback for exiting the application
@@ -530,5 +510,3 @@ bool easy_flipper_set_char_to_furi_string(FuriString** furi_string, char* buffer
     furi_string_set_str(*furi_string, buffer);
     return true;
 }
-
-#endif // EASY_FLIPPER_H

+ 261 - 0
flip_library/easy_flipper/easy_flipper.h

@@ -0,0 +1,261 @@
+#ifndef EASY_FLIPPER_H
+#define EASY_FLIPPER_H
+
+#include <malloc.h>
+#include <furi.h>
+#include <furi_hal.h>
+#include <gui/gui.h>
+#include <gui/view.h>
+#include <gui/modules/submenu.h>
+#include <gui/view_dispatcher.h>
+#include <gui/modules/menu.h>
+#include <gui/modules/submenu.h>
+#include <gui/modules/widget.h>
+#include <gui/modules/text_input.h>
+#include <gui/modules/text_box.h>
+#include <gui/modules/variable_item_list.h>
+#include <gui/modules/dialog_ex.h>
+#include <gui/modules/popup.h>
+#include <gui/modules/loading.h>
+#include <stdio.h>
+#include <string.h>
+#include <jsmn/jsmn.h>
+
+#define EASY_TAG "EasyFlipper"
+
+/**
+ * @brief Navigation callback for exiting the application
+ * @param context The context - unused
+ * @return next view id (VIEW_NONE to exit the app)
+ */
+uint32_t easy_flipper_callback_exit_app(void* context);
+/**
+ * @brief Initialize a buffer
+ * @param buffer The buffer to initialize
+ * @param buffer_size The size of the buffer
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_buffer(char** buffer, uint32_t buffer_size);
+/**
+ * @brief Initialize a View object
+ * @param view The View object to initialize
+ * @param view_id The ID/Index of the view
+ * @param draw_callback The draw callback function (set to NULL if not needed)
+ * @param input_callback The input callback function (set to NULL if not needed)
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_view(
+    View** view,
+    int32_t view_id,
+    void draw_callback(Canvas*, void*),
+    bool input_callback(InputEvent*, void*),
+    uint32_t (*previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a ViewDispatcher object
+ * @param view_dispatcher The ViewDispatcher object to initialize
+ * @param gui The GUI object
+ * @param context The context to pass to the event callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_view_dispatcher(ViewDispatcher** view_dispatcher, Gui* gui, void* context);
+
+/**
+ * @brief Initialize a Submenu object
+ * @note This does not set the items in the submenu
+ * @param submenu The Submenu object to initialize
+ * @param view_id The ID/Index of the view
+ * @param title The title/header of the submenu
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_submenu(
+    Submenu** submenu,
+    int32_t view_id,
+    char* title,
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher);
+
+/**
+ * @brief Initialize a Menu object
+ * @note This does not set the items in the menu
+ * @param menu The Menu object to initialize
+ * @param view_id The ID/Index of the view
+ * @param item_callback The item callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_menu(
+    Menu** menu,
+    int32_t view_id,
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher);
+
+/**
+ * @brief Initialize a Widget object
+ * @param widget The Widget object to initialize
+ * @param view_id The ID/Index of the view
+ * @param text The text to display in the widget
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_widget(
+    Widget** widget,
+    int32_t view_id,
+    char* text,
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher);
+
+/**
+ * @brief Initialize a VariableItemList object
+ * @note This does not set the items in the VariableItemList
+ * @param variable_item_list The VariableItemList object to initialize
+ * @param view_id The ID/Index of the view
+ * @param enter_callback The enter callback function (can be set to NULL)
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the enter callback (usually the app)
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_variable_item_list(
+    VariableItemList** variable_item_list,
+    int32_t view_id,
+    void (*enter_callback)(void*, uint32_t),
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a TextInput object
+ * @param text_input The TextInput object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_text_input(
+    TextInput** text_input,
+    int32_t view_id,
+    char* header_text,
+    char* text_input_temp_buffer,
+    uint32_t text_input_buffer_size,
+    void (*result_callback)(void*),
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a TextInput object with extra symbols
+ * @param uart_text_input The TextInput object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_uart_text_input(
+    TextInput** uart_text_input,
+    int32_t view_id,
+    char* header_text,
+    char* uart_text_input_temp_buffer,
+    uint32_t uart_text_input_buffer_size,
+    void (*result_callback)(void*),
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a DialogEx object
+ * @param dialog_ex The DialogEx object to initialize
+ * @param view_id The ID/Index of the view
+ * @param header The header of the dialog
+ * @param header_x The x coordinate of the header
+ * @param header_y The y coordinate of the header
+ * @param text The text of the dialog
+ * @param text_x The x coordinate of the dialog
+ * @param text_y The y coordinate of the dialog
+ * @param left_button_text The text of the left button
+ * @param right_button_text The text of the right button
+ * @param center_button_text The text of the center button
+ * @param result_callback The result callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the result callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_dialog_ex(
+    DialogEx** dialog_ex,
+    int32_t view_id,
+    char* header,
+    uint16_t header_x,
+    uint16_t header_y,
+    char* text,
+    uint16_t text_x,
+    uint16_t text_y,
+    char* left_button_text,
+    char* right_button_text,
+    char* center_button_text,
+    void (*result_callback)(DialogExResult, void*),
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a Popup object
+ * @param popup The Popup object to initialize
+ * @param view_id The ID/Index of the view
+ * @param header The header of the dialog
+ * @param header_x The x coordinate of the header
+ * @param header_y The y coordinate of the header
+ * @param text The text of the dialog
+ * @param text_x The x coordinate of the dialog
+ * @param text_y The y coordinate of the dialog
+ * @param result_callback The result callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the result callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_popup(
+    Popup** popup,
+    int32_t view_id,
+    char* header,
+    uint16_t header_x,
+    uint16_t header_y,
+    char* text,
+    uint16_t text_x,
+    uint16_t text_y,
+    void (*result_callback)(void*),
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher,
+    void* context);
+
+/**
+ * @brief Initialize a Loading object
+ * @param loading The Loading object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_loading(
+    Loading** loading,
+    int32_t view_id,
+    uint32_t(previous_callback)(void*),
+    ViewDispatcher** view_dispatcher);
+
+/**
+ * @brief Set a char butter to a FuriString
+ * @param furi_string The FuriString object
+ * @param buffer The buffer to copy the string to
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_char_to_furi_string(FuriString** furi_string, char* buffer);
+
+#endif

+ 4 - 5
flip_library/flip_library_free.h → flip_library/flip_library.c

@@ -1,8 +1,9 @@
-#ifndef FLIP_LIBRARY_FREE_H
-#define FLIP_LIBRARY_FREE_H
+#include "flip_library.h"
+
+FlipLibraryApp* app_instance = NULL;
 
 // Function to free the resources used by FlipLibraryApp
-static void flip_library_app_free(FlipLibraryApp* app) {
+void flip_library_app_free(FlipLibraryApp* app) {
     if(!app) {
         FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
         return;
@@ -79,5 +80,3 @@ static void flip_library_app_free(FlipLibraryApp* app) {
     // free the app
     free(app);
 }
-
-#endif // FLIP_LIBRARY_FREE_H

+ 6 - 3
flip_library/flip_library_e.h → flip_library/flip_library.h

@@ -1,8 +1,8 @@
 #ifndef FLIP_LIBRARY_E_H
 #define FLIP_LIBRARY_E_H
 
-#include <flipper_http.h>
-#include <easy_flipper.h>
+#include <flipper_http/flipper_http.h>
+#include <easy_flipper/easy_flipper.h>
 #include <furi.h>
 #include <furi_hal.h>
 #include <gui/gui.h>
@@ -11,7 +11,7 @@
 #include <gui/view_dispatcher.h>
 #include <notification/notification.h>
 #include <dialogs/dialogs.h>
-#include <jsmn.h>
+#include <jsmn/jsmn.h>
 
 #define TAG "FlipLibrary"
 
@@ -82,4 +82,7 @@ typedef struct {
     uint32_t uart_text_input_buffer_size_dictionary; // Size of the text input buffer (dictionary)
 } FlipLibraryApp;
 
+// Function to free the resources used by FlipLibraryApp
+void flip_library_app_free(FlipLibraryApp* app);
+extern FlipLibraryApp* app_instance;
 #endif // FLIP_LIBRARY_E_H

+ 3 - 11
flip_library/flip_library_storage.h → flip_library/flip_storage/flip_library_storage.c

@@ -1,12 +1,6 @@
-#ifndef FLIP_LIBRARY_STORAGE_H
-#define FLIP_LIBRARY_STORAGE_H
+#include <flip_storage/flip_library_storage.h>
 
-#include <furi.h>
-#include <storage/storage.h>
-
-#define SETTINGS_PATH STORAGE_EXT_PATH_PREFIX "/apps_data/flip_library/settings.bin"
-
-static void save_settings(const char* ssid, const char* password) {
+void save_settings(const char* ssid, const char* password) {
     // Create the directory for saving settings
     char directory_path[256];
     snprintf(
@@ -44,7 +38,7 @@ static void save_settings(const char* ssid, const char* password) {
     furi_record_close(RECORD_STORAGE);
 }
 
-static bool load_settings(char* ssid, size_t ssid_size, char* password, size_t password_size) {
+bool load_settings(char* ssid, size_t ssid_size, char* password, size_t password_size) {
     Storage* storage = furi_record_open(RECORD_STORAGE);
     File* file = storage_file_alloc(storage);
 
@@ -86,5 +80,3 @@ static bool load_settings(char* ssid, size_t ssid_size, char* password, size_t p
 
     return true;
 }
-
-#endif // FLIP_LIBRARY_STORAGE_H

+ 13 - 0
flip_library/flip_storage/flip_library_storage.h

@@ -0,0 +1,13 @@
+#ifndef FLIP_LIBRARY_STORAGE_H
+#define FLIP_LIBRARY_STORAGE_H
+
+#include <furi.h>
+#include <storage/storage.h>
+#include <flip_library.h>
+#define SETTINGS_PATH STORAGE_EXT_PATH_PREFIX "/apps_data/flip_library/settings.bin"
+
+void save_settings(const char* ssid, const char* password);
+
+bool load_settings(char* ssid, size_t ssid_size, char* password, size_t password_size);
+
+#endif // FLIP_LIBRARY_STORAGE_H

+ 10 - 144
flip_library/flipper_http.h → flip_library/flipper_http/flipper_http.c

@@ -1,137 +1,7 @@
-// flipper_http.h
-#ifndef FLIPPER_HTTP_H
-#define FLIPPER_HTTP_H
-
-#include <furi.h>
-#include <furi_hal.h>
-#include <furi_hal_gpio.h>
-#include <furi_hal_serial.h>
-#include <storage/storage.h>
-
-// STORAGE_EXT_PATH_PREFIX is defined in the Furi SDK as /ext
-
-#define HTTP_TAG               "FlipLibrary" // change this to your app name
-#define http_tag               "flip_library" // change this to your app id
-#define UART_CH                (FuriHalSerialIdUsart) // UART channel
-#define TIMEOUT_DURATION_TICKS (5 * 1000) // 5 seconds
-#define BAUDRATE               (115200) // UART baudrate
-#define RX_BUF_SIZE            1024 // UART RX buffer size
-#define RX_LINE_BUFFER_SIZE    4096 // UART RX line buffer size (increase for large responses)
-#define MAX_FILE_SHOW          4096 // Maximum data from file to show
-
-// Forward declaration for callback
-typedef void (*FlipperHTTP_Callback)(const char* line, void* context);
-
-// Functions
-bool flipper_http_init(FlipperHTTP_Callback callback, void* context);
-void flipper_http_deinit();
-//---
-void flipper_http_rx_callback(const char* line, void* context);
-bool flipper_http_send_data(const char* data);
-//---
-bool flipper_http_connect_wifi();
-bool flipper_http_disconnect_wifi();
-bool flipper_http_ping();
-bool flipper_http_scan_wifi();
-bool flipper_http_save_wifi(const char* ssid, const char* password);
-bool flipper_http_ip_wifi();
-bool flipper_http_ip_address();
-//---
-bool flipper_http_list_commands();
-bool flipper_http_led_on();
-bool flipper_http_led_off();
-bool flipper_http_parse_json(const char* key, const char* json_data);
-bool flipper_http_parse_json_array(const char* key, int index, const char* json_data);
-//---
-bool flipper_http_get_request(const char* url);
-bool flipper_http_get_request_with_headers(const char* url, const char* headers);
-bool flipper_http_post_request_with_headers(
-    const char* url,
-    const char* headers,
-    const char* payload);
-bool flipper_http_put_request_with_headers(
-    const char* url,
-    const char* headers,
-    const char* payload);
-bool flipper_http_delete_request_with_headers(
-    const char* url,
-    const char* headers,
-    const char* payload);
-//---
-bool flipper_http_get_request_bytes(const char* url, const char* headers);
-bool flipper_http_post_request_bytes(const char* url, const char* headers, const char* payload);
-//
-bool flipper_http_append_to_file(
-    const void* data,
-    size_t data_size,
-    bool start_new_file,
-    char* file_path);
-
-FuriString* flipper_http_load_from_file(char* file_path);
-static char* trim(const char* str);
-//
-bool flipper_http_process_response_async(bool (*http_request)(void), bool (*parse_json)(void));
-
-// State variable to track the UART state
-typedef enum {
-    INACTIVE, // Inactive state
-    IDLE, // Default state
-    RECEIVING, // Receiving data
-    SENDING, // Sending data
-    ISSUE, // Issue with connection
-} SerialState;
-
-// Event Flags for UART Worker Thread
-typedef enum {
-    WorkerEvtStop = (1 << 0),
-    WorkerEvtRxDone = (1 << 1),
-} WorkerEvtFlags;
-
-// FlipperHTTP Structure
-typedef struct {
-    FuriStreamBuffer* flipper_http_stream; // Stream buffer for UART communication
-    FuriHalSerialHandle* serial_handle; // Serial handle for UART communication
-    FuriThread* rx_thread; // Worker thread for UART
-    FuriThreadId rx_thread_id; // Worker thread ID
-    FlipperHTTP_Callback handle_rx_line_cb; // Callback for received lines
-    void* callback_context; // Context for the callback
-    SerialState state; // State of the UART
-
-    // variable to store the last received data from the UART
-    char* last_response;
-    char file_path[256]; // Path to save the received data
-
-    // Timer-related members
-    FuriTimer* get_timeout_timer; // Timer for HTTP request timeout
-
-    bool started_receiving_get; // Indicates if a GET request has started
-    bool just_started_get; // Indicates if GET data reception has just started
-
-    bool started_receiving_post; // Indicates if a POST request has started
-    bool just_started_post; // Indicates if POST data reception has just started
-
-    bool started_receiving_put; // Indicates if a PUT request has started
-    bool just_started_put; // Indicates if PUT data reception has just started
-
-    bool started_receiving_delete; // Indicates if a DELETE request has started
-    bool just_started_delete; // Indicates if DELETE data reception has just started
-
-    // Buffer to hold the raw bytes received from the UART
-    uint8_t* received_bytes;
-    size_t received_bytes_len; // Length of the received bytes
-    bool is_bytes_request; // Flag to indicate if the request is for bytes
-    bool save_bytes; // Flag to save the received data to a file
-    bool save_received_data; // Flag to save the received data to a file
-} FlipperHTTP;
-
-static FlipperHTTP fhttp;
-// Global static array for the line buffer
-static char rx_line_buffer[RX_LINE_BUFFER_SIZE];
-#define FILE_BUFFER_SIZE 512
-static uint8_t file_buffer[FILE_BUFFER_SIZE];
-
-// fhttp.last_response holds the last received data from the UART
-
+#include <flipper_http/flipper_http.h>
+FlipperHTTP fhttp;
+char rx_line_buffer[RX_LINE_BUFFER_SIZE];
+uint8_t file_buffer[FILE_BUFFER_SIZE];
 // Function to append received data to file
 // make sure to initialize the file path before calling this function
 bool flipper_http_append_to_file(
@@ -258,7 +128,7 @@ FuriString* flipper_http_load_from_file(char* file_path) {
  * @note       This function will handle received data asynchronously via the callback.
  */
 // UART worker thread
-static int32_t flipper_http_worker(void* context) {
+int32_t flipper_http_worker(void* context) {
     UNUSED(context);
     size_t rx_line_pos = 0;
     static size_t file_buffer_len = 0;
@@ -302,8 +172,6 @@ static int32_t flipper_http_worker(void* context) {
                         // Invoke the callback with the complete line
                         fhttp.handle_rx_line_cb(rx_line_buffer, fhttp.callback_context);
 
-                        // save the received data
-
                         // Reset the line buffer position
                         rx_line_pos = 0;
                     } else {
@@ -376,7 +244,7 @@ void get_timeout_timer_callback(void* context) {
  * @param      context   The context to pass to the callback.
  * @note       This function will handle received data asynchronously via the callback.
  */
-static void _flipper_http_rx_callback(
+void _flipper_http_rx_callback(
     FuriHalSerialHandle* handle,
     FuriHalSerialRxEvent event,
     void* context) {
@@ -550,13 +418,13 @@ bool flipper_http_send_data(const char* data) {
 
     // Create a buffer with data + '\n'
     size_t send_length = data_length + 1; // +1 for '\n'
-    if(send_length > 256) { // Ensure buffer size is sufficient
+    if(send_length > 512) { // Ensure buffer size is sufficient
         FURI_LOG_E("FlipperHTTP", "Data too long to send over FHTTP.");
         return false;
     }
 
-    char send_buffer[257]; // 256 + 1 for safety
-    strncpy(send_buffer, data, 256);
+    char send_buffer[513]; // 512 + 1 for safety
+    strncpy(send_buffer, data, 512);
     send_buffer[data_length] = '\n'; // Append newline
     send_buffer[data_length + 1] = '\0'; // Null-terminate
 
@@ -874,7 +742,7 @@ bool flipper_http_get_request_with_headers(const char* url, const char* headers)
     }
 
     // Prepare GET request command with headers
-    char command[256];
+    char command[512];
     int ret = snprintf(
         command, sizeof(command), "[GET/HTTP]{\"url\":\"%s\",\"headers\":%s}", url, headers);
     if(ret < 0 || ret >= (int)sizeof(command)) {
@@ -1388,5 +1256,3 @@ bool flipper_http_process_response_async(bool (*http_request)(void), bool (*pars
     }
     return true;
 }
-
-#endif // FLIPPER_HTTP_H

+ 360 - 0
flip_library/flipper_http/flipper_http.h

@@ -0,0 +1,360 @@
+// flipper_http.h
+#ifndef FLIPPER_HTTP_H
+#define FLIPPER_HTTP_H
+
+#include <furi.h>
+#include <furi_hal.h>
+#include <furi_hal_gpio.h>
+#include <furi_hal_serial.h>
+#include <storage/storage.h>
+
+// STORAGE_EXT_PATH_PREFIX is defined in the Furi SDK as /ext
+
+#define HTTP_TAG               "FlipLibrary" // change this to your app name
+#define http_tag               "flip_library" // change this to your app id
+#define UART_CH                (FuriHalSerialIdUsart) // UART channel
+#define TIMEOUT_DURATION_TICKS (5 * 1000) // 5 seconds
+#define BAUDRATE               (115200) // UART baudrate
+#define RX_BUF_SIZE            1024 // UART RX buffer size
+#define RX_LINE_BUFFER_SIZE    4096 // UART RX line buffer size (increase for large responses)
+#define MAX_FILE_SHOW          4096 // Maximum data from file to show
+#define FILE_BUFFER_SIZE       512 // File buffer size
+
+// Forward declaration for callback
+typedef void (*FlipperHTTP_Callback)(const char* line, void* context);
+
+// State variable to track the UART state
+typedef enum {
+    INACTIVE, // Inactive state
+    IDLE, // Default state
+    RECEIVING, // Receiving data
+    SENDING, // Sending data
+    ISSUE, // Issue with connection
+} SerialState;
+
+// Event Flags for UART Worker Thread
+typedef enum {
+    WorkerEvtStop = (1 << 0),
+    WorkerEvtRxDone = (1 << 1),
+} WorkerEvtFlags;
+
+// FlipperHTTP Structure
+typedef struct {
+    FuriStreamBuffer* flipper_http_stream; // Stream buffer for UART communication
+    FuriHalSerialHandle* serial_handle; // Serial handle for UART communication
+    FuriThread* rx_thread; // Worker thread for UART
+    FuriThreadId rx_thread_id; // Worker thread ID
+    FlipperHTTP_Callback handle_rx_line_cb; // Callback for received lines
+    void* callback_context; // Context for the callback
+    SerialState state; // State of the UART
+
+    // variable to store the last received data from the UART
+    char* last_response;
+    char file_path[256]; // Path to save the received data
+
+    // Timer-related members
+    FuriTimer* get_timeout_timer; // Timer for HTTP request timeout
+
+    bool started_receiving_get; // Indicates if a GET request has started
+    bool just_started_get; // Indicates if GET data reception has just started
+
+    bool started_receiving_post; // Indicates if a POST request has started
+    bool just_started_post; // Indicates if POST data reception has just started
+
+    bool started_receiving_put; // Indicates if a PUT request has started
+    bool just_started_put; // Indicates if PUT data reception has just started
+
+    bool started_receiving_delete; // Indicates if a DELETE request has started
+    bool just_started_delete; // Indicates if DELETE data reception has just started
+
+    // Buffer to hold the raw bytes received from the UART
+    uint8_t* received_bytes;
+    size_t received_bytes_len; // Length of the received bytes
+    bool is_bytes_request; // Flag to indicate if the request is for bytes
+    bool save_bytes; // Flag to save the received data to a file
+    bool save_received_data; // Flag to save the received data to a file
+} FlipperHTTP;
+
+extern FlipperHTTP fhttp;
+// Global static array for the line buffer
+extern char rx_line_buffer[RX_LINE_BUFFER_SIZE];
+extern uint8_t file_buffer[FILE_BUFFER_SIZE];
+
+// fhttp.last_response holds the last received data from the UART
+
+// Function to append received data to file
+// make sure to initialize the file path before calling this function
+bool flipper_http_append_to_file(
+    const void* data,
+    size_t data_size,
+    bool start_new_file,
+    char* file_path);
+
+FuriString* flipper_http_load_from_file(char* file_path);
+
+// UART worker thread
+/**
+ * @brief      Worker thread to handle UART data asynchronously.
+ * @return     0
+ * @param      context   The context to pass to the callback.
+ * @note       This function will handle received data asynchronously via the callback.
+ */
+// UART worker thread
+int32_t flipper_http_worker(void* context);
+
+// Timer callback function
+/**
+ * @brief      Callback function for the GET timeout timer.
+ * @return     0
+ * @param      context   The context to pass to the callback.
+ * @note       This function will be called when the GET request times out.
+ */
+void get_timeout_timer_callback(void* context);
+
+// UART RX Handler Callback (Interrupt Context)
+/**
+ * @brief      A private callback function to handle received data asynchronously.
+ * @return     void
+ * @param      handle    The UART handle.
+ * @param      event     The event type.
+ * @param      context   The context to pass to the callback.
+ * @note       This function will handle received data asynchronously via the callback.
+ */
+void _flipper_http_rx_callback(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* context);
+
+// UART initialization function
+/**
+ * @brief      Initialize UART.
+ * @return     true if the UART was initialized successfully, false otherwise.
+ * @param      callback  The callback function to handle received data (ex. flipper_http_rx_callback).
+ * @param      context   The context to pass to the callback.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_init(FlipperHTTP_Callback callback, void* context);
+
+// Deinitialize UART
+/**
+ * @brief      Deinitialize UART.
+ * @return     void
+ * @note       This function will stop the asynchronous RX, release the serial handle, and free the resources.
+ */
+void flipper_http_deinit();
+
+// Function to send data over UART with newline termination
+/**
+ * @brief      Send data over UART with newline termination.
+ * @return     true if the data was sent successfully, false otherwise.
+ * @param      data  The data to send over UART.
+ * @note       The data will be sent over UART with a newline character appended.
+ */
+bool flipper_http_send_data(const char* data);
+
+// Function to send a PING request
+/**
+ * @brief      Send a PING request to check if the Wifi Dev Board is connected.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ * @note       This is best used to check if the Wifi Dev Board is connected.
+ * @note       The state will remain INACTIVE until a PONG is received.
+ */
+bool flipper_http_ping();
+
+// Function to list available commands
+/**
+ * @brief      Send a command to list available commands.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_list_commands();
+
+// Function to turn on the LED
+/**
+ * @brief      Allow the LED to display while processing.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_led_on();
+
+// Function to turn off the LED
+/**
+ * @brief      Disable the LED from displaying while processing.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_led_off();
+
+// Function to parse JSON data
+/**
+ * @brief      Parse JSON data.
+ * @return     true if the JSON data was parsed successfully, false otherwise.
+ * @param      key       The key to parse from the JSON data.
+ * @param      json_data The JSON data to parse.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_parse_json(const char* key, const char* json_data);
+
+// Function to parse JSON array data
+/**
+ * @brief      Parse JSON array data.
+ * @return     true if the JSON array data was parsed successfully, false otherwise.
+ * @param      key       The key to parse from the JSON array data.
+ * @param      index     The index to parse from the JSON array data.
+ * @param      json_data The JSON array data to parse.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_parse_json_array(const char* key, int index, const char* json_data);
+
+// Function to scan for WiFi networks
+/**
+ * @brief      Send a command to scan for WiFi networks.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_scan_wifi();
+
+// Function to save WiFi settings (returns true if successful)
+/**
+ * @brief      Send a command to save WiFi settings.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_save_wifi(const char* ssid, const char* password);
+
+// Function to get IP address of WiFi Devboard
+/**
+ * @brief      Send a command to get the IP address of the WiFi Devboard
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_ip_address();
+
+// Function to get IP address of the connected WiFi network
+/**
+ * @brief      Send a command to get the IP address of the connected WiFi network.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_ip_wifi();
+
+// Function to disconnect from WiFi (returns true if successful)
+/**
+ * @brief      Send a command to disconnect from WiFi.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_disconnect_wifi();
+
+// Function to connect to WiFi (returns true if successful)
+/**
+ * @brief      Send a command to connect to WiFi.
+ * @return     true if the request was successful, false otherwise.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_connect_wifi();
+
+// Function to send a GET request
+/**
+ * @brief      Send a GET request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the GET request to.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_get_request(const char* url);
+
+// Function to send a GET request with headers
+/**
+ * @brief      Send a GET request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the GET request to.
+ * @param      headers  The headers to send with the GET request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_get_request_with_headers(const char* url, const char* headers);
+
+// Function to send a GET request with headers and return bytes
+/**
+ * @brief      Send a GET request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the GET request to.
+ * @param      headers  The headers to send with the GET request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_get_request_bytes(const char* url, const char* headers);
+
+// Function to send a POST request with headers
+/**
+ * @brief      Send a POST request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the POST request to.
+ * @param      headers  The headers to send with the POST request.
+ * @param      data  The data to send with the POST request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_post_request_with_headers(
+    const char* url,
+    const char* headers,
+    const char* payload);
+
+// Function to send a POST request with headers and return bytes
+/**
+ * @brief      Send a POST request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the POST request to.
+ * @param      headers  The headers to send with the POST request.
+ * @param      payload  The data to send with the POST request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_post_request_bytes(const char* url, const char* headers, const char* payload);
+
+// Function to send a PUT request with headers
+/**
+ * @brief      Send a PUT request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the PUT request to.
+ * @param      headers  The headers to send with the PUT request.
+ * @param      data  The data to send with the PUT request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_put_request_with_headers(
+    const char* url,
+    const char* headers,
+    const char* payload);
+
+// Function to send a DELETE request with headers
+/**
+ * @brief      Send a DELETE request to the specified URL.
+ * @return     true if the request was successful, false otherwise.
+ * @param      url  The URL to send the DELETE request to.
+ * @param      headers  The headers to send with the DELETE request.
+ * @param      data  The data to send with the DELETE request.
+ * @note       The received data will be handled asynchronously via the callback.
+ */
+bool flipper_http_delete_request_with_headers(
+    const char* url,
+    const char* headers,
+    const char* payload);
+
+// Function to handle received data asynchronously
+/**
+ * @brief      Callback function to handle received data asynchronously.
+ * @return     void
+ * @param      line     The received line.
+ * @param      context  The context passed to the callback.
+ * @note       The received data will be handled asynchronously via the callback and handles the state of the UART.
+ */
+void flipper_http_rx_callback(const char* line, void* context);
+
+// Function to trim leading and trailing spaces and newlines from a constant string
+char* trim(const char* str);
+/**
+ * @brief Process requests and parse JSON data asynchronously
+ * @param http_request The function to send the request
+ * @param parse_json The function to parse the JSON
+ * @return true if successful, false otherwise
+ */
+bool flipper_http_process_response_async(bool (*http_request)(void), bool (*parse_json)(void));
+
+#endif // FLIPPER_HTTP_H

+ 35 - 138
flip_library/jsmn.h → flip_library/jsmn/jsmn.c

@@ -3,113 +3,20 @@
  *
  * Copyright (c) 2010 Serge Zaitsev
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * [License text continues...]
  */
-#ifndef JSMN_H
-#define JSMN_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef JSMN_STATIC
-#define JSMN_API static
-#else
-#define JSMN_API extern
-#endif
-
-/**
-   * JSON type identifier. Basic types are:
-   * 	o Object
-   * 	o Array
-   * 	o String
-   * 	o Other primitive: number, boolean (true/false) or null
-   */
-typedef enum {
-    JSMN_UNDEFINED = 0,
-    JSMN_OBJECT = 1 << 0,
-    JSMN_ARRAY = 1 << 1,
-    JSMN_STRING = 1 << 2,
-    JSMN_PRIMITIVE = 1 << 3
-} jsmntype_t;
-
-enum jsmnerr {
-    /* Not enough tokens were provided */
-    JSMN_ERROR_NOMEM = -1,
-    /* Invalid character inside JSON string */
-    JSMN_ERROR_INVAL = -2,
-    /* The string is not a full JSON packet, more bytes expected */
-    JSMN_ERROR_PART = -3
-};
 
-/**
-   * JSON token description.
-   * type		type (object, array, string etc.)
-   * start	start position in JSON data string
-   * end		end position in JSON data string
-   */
-typedef struct jsmntok {
-    jsmntype_t type;
-    int start;
-    int end;
-    int size;
-#ifdef JSMN_PARENT_LINKS
-    int parent;
-#endif
-} jsmntok_t;
-
-/**
-   * JSON parser. Contains an array of token blocks available. Also stores
-   * the string being parsed now and current position in that string.
-   */
-typedef struct jsmn_parser {
-    unsigned int pos; /* offset in the JSON string */
-    unsigned int toknext; /* next token to allocate */
-    int toksuper; /* superior token node, e.g. parent object or array */
-} jsmn_parser;
-
-/**
-   * Create JSON parser over an array of tokens
-   */
-JSMN_API void jsmn_init(jsmn_parser* parser);
-
-/**
-   * Run JSON parser. It parses a JSON data string into and array of tokens, each
-   * describing
-   * a single JSON object.
-   */
-JSMN_API int jsmn_parse(
-    jsmn_parser* parser,
-    const char* js,
-    const size_t len,
-    jsmntok_t* tokens,
-    const unsigned int num_tokens);
+#include <jsmn/jsmn.h>
+#include <stdlib.h>
+#include <string.h>
 
-#ifndef JSMN_HEADER
 /**
-   * Allocates a fresh unused token from the token pool.
-   */
+ * Allocates a fresh unused token from the token pool.
+ */
 static jsmntok_t*
     jsmn_alloc_token(jsmn_parser* parser, jsmntok_t* tokens, const size_t num_tokens) {
     jsmntok_t* tok;
+
     if(parser->toknext >= num_tokens) {
         return NULL;
     }
@@ -123,8 +30,8 @@ static jsmntok_t*
 }
 
 /**
-   * Fills token type and boundaries.
-   */
+ * Fills token type and boundaries.
+ */
 static void
     jsmn_fill_token(jsmntok_t* token, const jsmntype_t type, const int start, const int end) {
     token->type = type;
@@ -134,8 +41,8 @@ static void
 }
 
 /**
-   * Fills next available token with JSON primitive.
-   */
+ * Fills next available token with JSON primitive.
+ */
 static int jsmn_parse_primitive(
     jsmn_parser* parser,
     const char* js,
@@ -195,8 +102,8 @@ found:
 }
 
 /**
-   * Fills next token with JSON string.
-   */
+ * Fills next token with JSON string.
+ */
 static int jsmn_parse_string(
     jsmn_parser* parser,
     const char* js,
@@ -272,9 +179,18 @@ static int jsmn_parse_string(
 }
 
 /**
-   * Parse JSON string and fill tokens.
-   */
-JSMN_API int jsmn_parse(
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser* parser) {
+    parser->pos = 0;
+    parser->toknext = 0;
+    parser->toksuper = -1;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(
     jsmn_parser* parser,
     const char* js,
     const size_t len,
@@ -464,33 +380,16 @@ JSMN_API int jsmn_parse(
     return count;
 }
 
-/**
-   * Creates a new parser based over a given buffer with an array of tokens
-   * available.
-   */
-JSMN_API void jsmn_init(jsmn_parser* parser) {
-    parser->pos = 0;
-    parser->toknext = 0;
-    parser->toksuper = -1;
-}
-
-#endif /* JSMN_HEADER */
-
-#ifdef __cplusplus
+// Helper function to create a JSON object
+char* jsmn(const char* key, const char* value) {
+    int length = strlen(key) + strlen(value) + 8; // Calculate required length
+    char* result = (char*)malloc(length * sizeof(char)); // Allocate memory
+    if(result == NULL) {
+        return NULL; // Handle memory allocation failure
+    }
+    snprintf(result, length, "{\"%s\":\"%s\"}", key, value);
+    return result; // Caller is responsible for freeing this memory
 }
-#endif
-
-#endif /* JSMN_H */
-
-#ifndef JB_JSMN_EDIT
-#define JB_JSMN_EDIT
-/* Added in by JBlanked on 2024-10-16 for use in Flipper Zero SDK*/
-
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <furi.h>
 
 // Helper function to compare JSON keys
 int jsoneq(const char* json, jsmntok_t* tok, const char* s) {
@@ -501,7 +400,7 @@ int jsoneq(const char* json, jsmntok_t* tok, const char* s) {
     return -1;
 }
 
-// return the value of the key in the JSON data
+// Return the value of the key in the JSON data
 char* get_json_value(char* key, char* json_data, uint32_t max_tokens) {
     // Parse the JSON feed
     if(json_data != NULL) {
@@ -765,5 +664,3 @@ char** get_json_array_values(char* key, char* json_data, uint32_t max_tokens, in
     free(array_str);
     return values;
 }
-
-#endif /* JB_JSMN_EDIT */

+ 131 - 0
flip_library/jsmn/jsmn.h

@@ -0,0 +1,131 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2010 Serge Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * [License text continues...]
+ */
+
+#ifndef JSMN_H
+#define JSMN_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef JSMN_STATIC
+#define JSMN_API static
+#else
+#define JSMN_API extern
+#endif
+
+/**
+     * JSON type identifier. Basic types are:
+     * 	o Object
+     * 	o Array
+     * 	o String
+     * 	o Other primitive: number, boolean (true/false) or null
+     */
+typedef enum {
+    JSMN_UNDEFINED = 0,
+    JSMN_OBJECT = 1 << 0,
+    JSMN_ARRAY = 1 << 1,
+    JSMN_STRING = 1 << 2,
+    JSMN_PRIMITIVE = 1 << 3
+} jsmntype_t;
+
+enum jsmnerr {
+    /* Not enough tokens were provided */
+    JSMN_ERROR_NOMEM = -1,
+    /* Invalid character inside JSON string */
+    JSMN_ERROR_INVAL = -2,
+    /* The string is not a full JSON packet, more bytes expected */
+    JSMN_ERROR_PART = -3
+};
+
+/**
+     * JSON token description.
+     * type		type (object, array, string etc.)
+     * start	start position in JSON data string
+     * end		end position in JSON data string
+     */
+typedef struct {
+    jsmntype_t type;
+    int start;
+    int end;
+    int size;
+#ifdef JSMN_PARENT_LINKS
+    int parent;
+#endif
+} jsmntok_t;
+
+/**
+     * JSON parser. Contains an array of token blocks available. Also stores
+     * the string being parsed now and current position in that string.
+     */
+typedef struct {
+    unsigned int pos; /* offset in the JSON string */
+    unsigned int toknext; /* next token to allocate */
+    int toksuper; /* superior token node, e.g. parent object or array */
+} jsmn_parser;
+
+/**
+     * Create JSON parser over an array of tokens
+     */
+JSMN_API void jsmn_init(jsmn_parser* parser);
+
+/**
+     * Run JSON parser. It parses a JSON data string into and array of tokens, each
+     * describing a single JSON object.
+     */
+JSMN_API int jsmn_parse(
+    jsmn_parser* parser,
+    const char* js,
+    const size_t len,
+    jsmntok_t* tokens,
+    const unsigned int num_tokens);
+
+#ifndef JSMN_HEADER
+/* Implementation has been moved to jsmn.c */
+#endif /* JSMN_HEADER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSMN_H */
+
+/* Custom Helper Functions */
+#ifndef JB_JSMN_EDIT
+#define JB_JSMN_EDIT
+/* Added in by JBlanked on 2024-10-16 for use in Flipper Zero SDK*/
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <furi.h>
+
+// Helper function to create a JSON object
+char* jsmn(const char* key, const char* value);
+// Helper function to compare JSON keys
+int jsoneq(const char* json, jsmntok_t* tok, const char* s);
+
+// Return the value of the key in the JSON data
+char* get_json_value(char* key, char* json_data, uint32_t max_tokens);
+
+// Revised get_json_array_value function
+char* get_json_array_value(char* key, uint32_t index, char* json_data, uint32_t max_tokens);
+
+// Revised get_json_array_values function with correct token skipping
+char** get_json_array_values(char* key, char* json_data, uint32_t max_tokens, int* num_values);
+#endif /* JB_JSMN_EDIT */