Procházet zdrojové kódy

Merge flip_wifi from https://github.com/jblanked/FlipWiFi

# Conflicts:
#	flip_wifi/flipper_http/flipper_http.h
Willy-JL před 9 měsíci
rodič
revize
f2525bc610

+ 5 - 0
flip_wifi/CHANGELOG.md

@@ -1,3 +1,8 @@
+## v1.4
+- Updated to the latest FlipperHTTP library.
+- Added a check to verify the WiFi connection was successful.
+- Updated the WiFi scan to use JSON for handling unconventional network names.
+
 ## v1.3.2
 - Fixed a crash that occurred when deleting a network from the Saved APs list.
 - Updated to connect to the network after clicking "Set" on the selected SSID in the Saved APs list.

+ 1 - 1
flip_wifi/README.md

@@ -2,7 +2,7 @@ FlipWiFi is the companion app for the popular FlipperHTTP flash, originally intr
 
 ## Requirements
 
-- WiFi Developer Board, Raspberry Pi, or ESP32 Device with FlipperHTTP Flash: https://github.com/jblanked/FlipperHTTP
+- WiFi Developer Board, Raspberry Pi, or ESP32 Device flashed with FlipperHTTP v1.8.2 or higher: https://github.com/jblanked/FlipperHTTP
 - 2.4 GHz WiFi Access Point
 
 ## Features

+ 1 - 1
flip_wifi/alloc/flip_wifi_alloc.c

@@ -14,7 +14,7 @@ FlipWiFiApp *flip_wifi_app_alloc()
     }
 
     // Submenu
-    if (!easy_flipper_set_submenu(&app->submenu_main, FlipWiFiViewSubmenuMain, "FlipWiFi v1.3.2", callback_exit_app, &app->view_dispatcher))
+    if (!easy_flipper_set_submenu(&app->submenu_main, FlipWiFiViewSubmenuMain, "FlipWiFi v1.4", callback_exit_app, &app->view_dispatcher))
     {
         return NULL;
     }

+ 21 - 22
flip_wifi/app.c

@@ -15,33 +15,32 @@ int32_t flip_wifi_main(void *p)
     }
 
     // check if board is connected (Derek Jamison)
-    // initialize the http
-    if (flipper_http_init(flipper_http_rx_callback, app))
+    FlipperHTTP *fhttp = flipper_http_alloc();
+    if (!fhttp)
     {
-        if (!flipper_http_ping())
-        {
-            FURI_LOG_E(TAG, "Failed to ping the device");
-            return -1;
-        }
-
-        // Try to wait for pong response.
-        uint8_t counter = 10;
-        while (fhttp.state == INACTIVE && --counter > 0)
-        {
-            FURI_LOG_D(TAG, "Waiting for PONG");
-            furi_delay_ms(100);
-        }
-
-        if (counter == 0)
-            easy_flipper_dialog("FlipperHTTP Error", "Ensure your WiFi Developer\nBoard or Pico W is connected\nand the latest FlipperHTTP\nfirmware is installed.");
-
-        flipper_http_deinit();
+        easy_flipper_dialog("FlipperHTTP Error", "The UART is likely busy.\nEnsure you have the correct\nflash for your board then\nrestart your Flipper Zero.");
+        return -1;
     }
-    else
+
+    if (!flipper_http_send_command(fhttp, HTTP_CMD_PING))
     {
-        easy_flipper_dialog("FlipperHTTP Error", "The UART is likely busy.\nEnsure you have the correct\nflash for your board then\nrestart your Flipper Zero.");
+        FURI_LOG_E(TAG, "Failed to ping the device");
+        flipper_http_free(fhttp);
+        return -1;
     }
 
+    // Try to wait for pong response.
+    uint32_t counter = 10;
+    while (fhttp->state == INACTIVE && --counter > 0)
+    {
+        FURI_LOG_D(TAG, "Waiting for PONG");
+        furi_delay_ms(100); // this causes a BusFault
+    }
+    flipper_http_free(fhttp);
+
+    if (counter == 0)
+        easy_flipper_dialog("FlipperHTTP Error", "Ensure your WiFi Developer\nBoard or Pico W is connected\nand the latest FlipperHTTP\nfirmware is installed.");
+
     // Run the view dispatcher
     view_dispatcher_run(app->view_dispatcher);
 

+ 1 - 1
flip_wifi/application.fam

@@ -9,6 +9,6 @@ App(
     fap_icon_assets="assets",
     fap_author="JBlanked",
     fap_weburl="https://github.com/jblanked/FlipWiFi",
-    fap_version="1.3.2",
+    fap_version="1.4",
     fap_description="FlipperHTTP companion app.",
 )

binární
flip_wifi/assets/01-home.png


+ 114 - 168
flip_wifi/callback/flip_wifi_callback.c

@@ -133,7 +133,7 @@ static bool flip_wifi_alloc_widgets(void *context, uint32_t widget)
     case FlipWiFiViewAbout:
         if (!app->widget_info)
         {
-            if (!easy_flipper_set_widget(&app->widget_info, FlipWiFiViewAbout, "FlipWiFi v1.3.2\n-----\nFlipperHTTP companion app.\nScan and save WiFi networks.\n-----\nwww.github.com/jblanked", callback_to_submenu_main, &app->view_dispatcher))
+            if (!easy_flipper_set_widget(&app->widget_info, FlipWiFiViewAbout, "FlipWiFi v1.4\n-----\nFlipperHTTP companion app.\nScan and save WiFi networks.\n-----\nwww.github.com/jblanked", callback_to_submenu_main, &app->view_dispatcher))
             {
                 return false;
             }
@@ -263,17 +263,23 @@ static void flip_wifi_custom_command_updated(void *context)
         FURI_LOG_E(TAG, "Text input buffer is empty");
         return;
     }
+    FlipperHTTP *fhttp = flipper_http_alloc();
+    if (!fhttp)
+    {
+        FURI_LOG_E(TAG, "Failed to allocate FlipperHTTP");
+        return;
+    }
     // Send the custom command
-    flipper_http_send_data(app->uart_text_input_temp_buffer);
-    while (fhttp.last_response == NULL || strlen(fhttp.last_response) == 0)
+    flipper_http_send_data(fhttp, app->uart_text_input_temp_buffer);
+    while (fhttp->last_response == NULL || strlen(fhttp->last_response) == 0)
     {
         furi_delay_ms(100);
     }
     // Switch to the view
     char response[100];
-    snprintf(response, sizeof(response), "%s", fhttp.last_response);
+    snprintf(response, sizeof(response), "%s", fhttp->last_response);
     easy_flipper_dialog("", response);
-    flipper_http_deinit();
+    flipper_http_free(fhttp);
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipWiFiViewSubmenu);
 }
 
@@ -564,28 +570,38 @@ static bool flip_wifi_view_input_callback_saved(InputEvent *event, void *context
         save_settings(wifi_playlist->ssids[ssid_index], wifi_playlist->passwords[ssid_index]);
 
         // initialize uart
-        if (!flipper_http_init(flipper_http_rx_callback, app))
+        FlipperHTTP *fhttp = flipper_http_alloc();
+        if (!fhttp)
         {
             easy_flipper_dialog("[ERROR]", "Failed to initialize flipper http");
             return false;
         }
 
         // clear response
-        if (fhttp.last_response)
-            snprintf(fhttp.last_response, RX_BUF_SIZE, "%s", "");
+        if (fhttp->last_response)
+            snprintf(fhttp->last_response, RX_BUF_SIZE, "%s", "");
 
-        if (!flipper_http_save_wifi(wifi_playlist->ssids[ssid_index], wifi_playlist->passwords[ssid_index]))
+        if (!flipper_http_save_wifi(fhttp, wifi_playlist->ssids[ssid_index], wifi_playlist->passwords[ssid_index]))
         {
             easy_flipper_dialog("[ERROR]", "Failed to save WiFi settings");
             return false;
         }
 
-        while (!fhttp.last_response || strlen(fhttp.last_response) == 0)
+        while (!fhttp->last_response || strlen(fhttp->last_response) == 0)
         {
             furi_delay_ms(100);
         }
 
-        flipper_http_deinit();
+        flipper_http_free(fhttp);
+
+        // check success (if [SUCCESS] is in the response)
+        if (strstr(fhttp->last_response, "[SUCCESS]") == NULL)
+        {
+            char response[512];
+            snprintf(response, sizeof(response), "Failed to save WiFi settings:\n%s", fhttp->last_response);
+            easy_flipper_dialog("[ERROR]", response);
+            return false;
+        }
 
         easy_flipper_dialog("[SUCCESS]", "All FlipperHTTP apps will now\nuse the selected network.");
         return true;
@@ -622,171 +638,108 @@ static bool flip_wifi_view_input_callback_saved(InputEvent *event, void *context
     }
     return false;
 }
-
-// Function to trim leading and trailing whitespace
-// Returns the trimmed start pointer and updates the length
-static char *trim_whitespace(char *start, size_t *length)
-{
-    // Trim leading whitespace
-    while (*length > 0 && isspace((unsigned char)*start))
-    {
-        start++;
-        (*length)--;
-    }
-
-    // Trim trailing whitespace
-    while (*length > 0 && isspace((unsigned char)start[*length - 1]))
-    {
-        (*length)--;
-    }
-
-    return start;
-}
-
-static bool flip_wifi_handle_scan(void *context)
+void callback_submenu_choices(void *context, uint32_t index)
 {
     FlipWiFiApp *app = (FlipWiFiApp *)context;
     if (!app)
     {
         FURI_LOG_E(TAG, "FlipWiFiApp is NULL");
-        return false;
+        return;
     }
-    // load the received data from the saved file
-    FuriString *scan_data = flipper_http_load_from_file(fhttp.file_path);
-    if (scan_data == NULL)
+    // initialize uart
+    FlipperHTTP *fhttp = flipper_http_alloc();
+    if (!fhttp)
     {
-        FURI_LOG_E(TAG, "Failed to load received data from file.");
-        fhttp.state = ISSUE;
-        easy_flipper_dialog("[ERROR]", "Failed to load data from /apps_data/flip_wifi/data/scan.txt");
-        return false;
+        easy_flipper_dialog("[ERROR]", "Failed to initialize flipper http");
+        return;
     }
-
-    uint32_t ssid_count = 0;
-
-    char *current_position = (char *)furi_string_get_cstr(scan_data);
-    char *next_comma = NULL;
-
-    // Manually split the string on commas
-    while ((next_comma = strchr(current_position, ',')) != NULL)
+    switch (index)
     {
-        // Calculate length of the SSID
-        size_t ssid_length = next_comma - current_position;
-
-        // Trim leading and trailing whitespace
-        size_t trimmed_length = ssid_length;
-        char *trim_start = trim_whitespace(current_position, &trimmed_length);
-
-        // Handle empty SSIDs resulting from consecutive commas
-        if (trimmed_length == 0)
+    case FlipWiFiSubmenuIndexWiFiScan:
+        flip_wifi_free_all(app);
+        if (!flip_wifi_alloc_submenus(app, FlipWiFiViewSubmenuScan))
         {
-            current_position = next_comma + 1; // Move past the comma
-            continue;
+            easy_flipper_dialog("[ERROR]", "Failed to allocate submenus for WiFi Scan");
+            return;
         }
 
-        // Allocate memory for the SSID and copy it
-        ssid_list[ssid_count] = malloc(trimmed_length + 1);
-        if (ssid_list[ssid_count] == NULL)
+        // scan for wifi ad parse the results
+        bool _flip_wifi_scan()
         {
-            FURI_LOG_E(TAG, "Memory allocation failed");
-            easy_flipper_dialog("[ERROR]", "Memory allocation failed");
-            furi_string_free(scan_data);
-            return false;
-        }
-        strncpy(ssid_list[ssid_count], trim_start, trimmed_length);
-        ssid_list[ssid_count][trimmed_length] = '\0'; // Null-terminate the string
+            // storage setup
+            Storage *storage = furi_record_open(RECORD_STORAGE);
 
-        ssid_count++;
-        if (ssid_count >= MAX_SCAN_NETWORKS)
-        {
-            FURI_LOG_E(TAG, "Maximum SSID limit reached");
-            break;
-        }
+            snprintf(fhttp->file_path, sizeof(fhttp->file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi/data/scan.txt");
+            storage_simply_remove_recursive(storage, fhttp->file_path); // ensure the file is empty
 
-        current_position = next_comma + 1; // Move past the comma
-    }
+            // ensure flip_wifi directory is there
+            char directory_path[128];
+            snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi");
+            storage_common_mkdir(storage, directory_path);
 
-    // Handle the last SSID after the last comma (if any)
-    if (*current_position != '\0' && ssid_count < MAX_SCAN_NETWORKS)
-    {
-        size_t ssid_length = strlen(current_position);
+            snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi/data");
+            storage_common_mkdir(storage, directory_path);
 
-        // Trim leading and trailing whitespace
-        size_t trimmed_length = ssid_length;
-        char *trim_start = trim_whitespace(current_position, &trimmed_length);
+            furi_record_close(RECORD_STORAGE);
 
-        // Handle empty SSIDs
-        if (trimmed_length > 0)
+            fhttp->just_started = true;
+            fhttp->save_received_data = true;
+            return flipper_http_send_command(fhttp, HTTP_CMD_SCAN);
+        }
+
+        bool _flip_wifi_handle_scan()
         {
-            ssid_list[ssid_count] = malloc(trimmed_length + 1);
-            if (ssid_list[ssid_count] == NULL)
+            // load the received data from the saved file
+            FuriString *scan_data = flipper_http_load_from_file(fhttp->file_path);
+            if (scan_data == NULL)
             {
-                FURI_LOG_E(TAG, "Memory allocation failed for the last SSID");
-                easy_flipper_dialog("[ERROR]", "Memory allocation failed for the last SSID");
+                FURI_LOG_E(TAG, "Failed to load received data from file.");
+                easy_flipper_dialog("[ERROR]", "Failed to load data from /apps_data/flip_wifi/data/scan.txt");
                 return false;
             }
-            strncpy(ssid_list[ssid_count], trim_start, trimmed_length);
-            ssid_list[ssid_count][trimmed_length] = '\0'; // Null-terminate the string
-            ssid_count++;
-        }
-    }
 
-    // Add each SSID as a submenu item
-    submenu_reset(app->submenu_wifi);
-    submenu_set_header(app->submenu_wifi, "WiFi Nearby");
-    for (uint32_t i = 0; i < ssid_count; i++)
-    {
-        char *ssid_item = ssid_list[i];
-        if (ssid_item == NULL)
-        {
-            // skip any NULL entries
-            continue;
-        }
-        char ssid[64];
-        snprintf(ssid, sizeof(ssid), "%s", ssid_item);
-        submenu_add_item(app->submenu_wifi, ssid, FlipWiFiSubmenuIndexWiFiScanStart + i, callback_submenu_choices, app);
-    }
-    furi_string_free(scan_data);
-    return true;
-}
-void callback_submenu_choices(void *context, uint32_t index)
-{
-    FlipWiFiApp *app = (FlipWiFiApp *)context;
-    if (!app)
-    {
-        FURI_LOG_E(TAG, "FlipWiFiApp is NULL");
-        return;
-    }
-    switch (index)
-    {
-    case FlipWiFiSubmenuIndexWiFiScan:
-        flip_wifi_free_all(app);
-        if (!flip_wifi_alloc_submenus(app, FlipWiFiViewSubmenuScan))
-        {
-            easy_flipper_dialog("[ERROR]", "Failed to allocate submenus for WiFi Scan");
-            return;
-        }
-        // initialize uart
-        if (!flipper_http_init(flipper_http_rx_callback, app))
-        {
-            easy_flipper_dialog("[ERROR]", "Failed to initialize flipper http");
-            return;
-        }
-        bool _flip_wifi_handle_scan()
-        {
-            return flip_wifi_handle_scan(app);
+            uint8_t ssid_count = 0;
+
+            for (uint8_t i = 0; i < MAX_SCAN_NETWORKS; i++)
+            {
+                char *ssid_item = get_json_array_value("networks", i, furi_string_get_cstr(scan_data));
+                if (ssid_item == NULL)
+                {
+                    // end of the list
+                    break;
+                }
+                ssid_list[i] = malloc(MAX_SSID_LENGTH);
+                if (ssid_list[i] == NULL)
+                {
+                    FURI_LOG_E(TAG, "Failed to allocate memory for SSID");
+                    furi_string_free(scan_data);
+                    return false;
+                }
+                snprintf(ssid_list[i], MAX_SSID_LENGTH, "%s", ssid_item);
+                free(ssid_item);
+                ssid_count++;
+            }
+
+            // Add each SSID as a submenu item
+            submenu_reset(app->submenu_wifi);
+            submenu_set_header(app->submenu_wifi, "WiFi Nearby");
+            for (uint8_t i = 0; i < ssid_count; i++)
+            {
+                char *ssid_item = ssid_list[i];
+                if (ssid_item == NULL)
+                {
+                    // end of the list
+                    break;
+                }
+                char ssid[64];
+                snprintf(ssid, sizeof(ssid), "%s", ssid_item);
+                submenu_add_item(app->submenu_wifi, ssid, FlipWiFiSubmenuIndexWiFiScanStart + i, callback_submenu_choices, app);
+            }
+            furi_string_free(scan_data);
+            return true;
         }
-        Storage *storage = furi_record_open(RECORD_STORAGE);
-        // ensure flip_wifi directory is there
-        char directory_path[128];
-        snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi");
-        storage_common_mkdir(storage, directory_path);
-        // ensure directory is there for saving data
-        snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi/data");
-        storage_common_mkdir(storage, directory_path);
-        furi_record_close(RECORD_STORAGE);
-        // scan for wifi ad parse the results
-        flipper_http_loading_task(flipper_http_scan_wifi, _flip_wifi_handle_scan, FlipWiFiViewSubmenu, FlipWiFiViewSubmenuMain, &app->view_dispatcher);
-        flipper_http_deinit();
+
+        flipper_http_loading_task(fhttp, _flip_wifi_scan, _flip_wifi_handle_scan, FlipWiFiViewSubmenu, FlipWiFiViewSubmenuMain, &app->view_dispatcher);
         break;
     case FlipWiFiSubmenuIndexWiFiSaved:
         flip_wifi_free_all(app);
@@ -825,12 +778,6 @@ void callback_submenu_choices(void *context, uint32_t index)
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipWiFiViewSubmenu);
         break;
     case FlipWiFiSubmenuIndexFastCommandStart ... FlipWiFiSubmenuIndexFastCommandStart + 4:
-        // initialize uart
-        if (!flipper_http_init(flipper_http_rx_callback, app))
-        {
-            easy_flipper_dialog("[ERROR]", "Failed to initialize flipper http");
-            return;
-        }
         // Handle fast commands
         switch (index)
         {
@@ -846,35 +793,34 @@ void callback_submenu_choices(void *context, uint32_t index)
             return;
         case FlipWiFiSubmenuIndexFastCommandStart + 1:
             // PING
-            flipper_http_ping();
+            flipper_http_send_command(fhttp, HTTP_CMD_PING);
             break;
         case FlipWiFiSubmenuIndexFastCommandStart + 2:
             // LIST
-            flipper_http_list_commands();
+            flipper_http_send_command(fhttp, HTTP_CMD_LIST_COMMANDS);
             break;
         case FlipWiFiSubmenuIndexFastCommandStart + 3:
             // IP/ADDRESS
-            flipper_http_ip_address();
+            flipper_http_send_command(fhttp, HTTP_CMD_IP_ADDRESS);
             break;
         case FlipWiFiSubmenuIndexFastCommandStart + 4:
             // WIFI/IP
-            flipper_http_ip_wifi();
+            flipper_http_send_command(fhttp, HTTP_CMD_IP_WIFI);
             break;
         default:
             break;
         }
-        while (fhttp.last_response == NULL || strlen(fhttp.last_response) == 0)
+        while (fhttp->last_response == NULL || strlen(fhttp->last_response) == 0)
         {
             // Wait for the response
             furi_delay_ms(100);
         }
-        if (fhttp.last_response != NULL)
+        if (fhttp->last_response != NULL)
         {
             char response[100];
-            snprintf(response, sizeof(response), "%s", fhttp.last_response);
+            snprintf(response, sizeof(response), "%s", fhttp->last_response);
             easy_flipper_dialog("", response);
         }
-        flipper_http_deinit();
         break;
     case 100 ... 199:
         ssid_index = index - FlipWiFiSubmenuIndexWiFiScanStart;
@@ -901,6 +847,7 @@ void callback_submenu_choices(void *context, uint32_t index)
     default:
         break;
     }
+    flipper_http_free(fhttp);
 }
 
 void flip_wifi_text_updated_password_scan(void *context)
@@ -936,8 +883,7 @@ void flip_wifi_text_updated_password_scan(void *context)
         FURI_LOG_E(TAG, "Playlist is full. Cannot add more entries.");
         return;
     }
-    FURI_LOG_I(TAG, "Adding SSID: %s", ssid_list[ssid_index]);
-    FURI_LOG_I(TAG, "Count: %d", wifi_playlist->count);
+
     // Add the SSID and password to the playlist
     snprintf(wifi_playlist->ssids[wifi_playlist->count], MAX_SSID_LENGTH, "%s", ssid_list[ssid_index]);
     snprintf(wifi_playlist->passwords[wifi_playlist->count], MAX_SSID_LENGTH, "%s", app->uart_text_input_buffer);

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 756 - 706
flip_wifi/flipper_http/flipper_http.c


+ 160 - 287
flip_wifi/flipper_http/flipper_http.h

@@ -1,6 +1,8 @@
-// flipper_http.h
-#ifndef FLIPPER_HTTP_H
-#define FLIPPER_HTTP_H
+// Description: Flipper HTTP API (For use with Flipper Zero and the FlipperHTTP flash: https://github.com/jblanked/FlipperHTTP)
+// License: MIT
+// Author: JBlanked
+// File: flipper_http.h
+#pragma once
 
 #include <gui/gui.h>
 #include <gui/view.h>
@@ -13,374 +15,245 @@
 #include <storage/storage.h>
 #include <momentum/settings.h>
 
-// STORAGE_EXT_PATH_PREFIX is defined in the Furi SDK as /ext
-
-#define HTTP_TAG "FlipWiFi"               // change this to your app name
-#define http_tag "flip_wifi"              // change this to your app id
-#define UART_CH (momentum_settings.uart_esp_channel)    // UART channel
-#define TIMEOUT_DURATION_TICKS (5 * 1000) // 5 seconds
-#define BAUDRATE (115200)                 // UART baudrate
-#define RX_BUF_SIZE 2048                  // 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
+#define HTTP_TAG               "FlipWiFi" // change this to your app name
+#define http_tag               "flip_wifi" // change this to your app id
+#define UART_CH                (momentum_settings.uart_esp_channel) // UART channel
+#define TIMEOUT_DURATION_TICKS (15 * 1000) // 15 seconds (for WiFi scanning)
+#define BAUDRATE               (115200) // UART baudrate
+#define RX_BUF_SIZE            2048 // 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);
+typedef void (*FlipperHTTP_Callback)(const char* line, void* context);
 
 // State variable to track the UART state
-typedef enum
-{
-    INACTIVE,  // Inactive state
-    IDLE,      // Default state
+typedef enum {
+    INACTIVE, // Inactive state
+    IDLE, // Default state
     RECEIVING, // Receiving data
-    SENDING,   // Sending data
-    ISSUE,     // Issue with connection
-} SerialState;
+    SENDING, // Sending data
+    ISSUE, // Issue with connection
+} HTTPState;
 
 // Event Flags for UART Worker Thread
-typedef enum
-{
+typedef enum {
     WorkerEvtStop = (1 << 0),
     WorkerEvtRxDone = (1 << 1),
 } WorkerEvtFlags;
 
+typedef enum {
+    GET, // GET request
+    POST, // POST request
+    PUT, // PUT request
+    DELETE, // DELETE request
+    //
+    BYTES, // Stream bytes to file
+    BYTES_POST, // Stream bytes to file after a POST request
+} HTTPMethod;
+
+typedef enum {
+    HTTP_CMD_WIFI_CONNECT,
+    HTTP_CMD_WIFI_DISCONNECT,
+    HTTP_CMD_IP_ADDRESS,
+    HTTP_CMD_IP_WIFI,
+    HTTP_CMD_SCAN,
+    HTTP_CMD_LIST_COMMANDS,
+    HTTP_CMD_LED_ON,
+    HTTP_CMD_LED_OFF,
+    HTTP_CMD_PING
+} HTTPCommand; // list of non-input commands
+
 // 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
+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;
+    void* callback_context; // Context for the callback
+    HTTPState state; // State of the UART
+    HTTPMethod method; // HTTP method
+    char* last_response; // variable to store the last received data from the UART
     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
-
+    FuriTimer* get_timeout_timer; // Timer for HTTP request timeout
+    bool started_receiving; // Indicates if a request has started
+    bool just_started; // Indicates if data reception has just started
+    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
     bool just_started_bytes; // Indicates if bytes data reception has just started
+    size_t bytes_received; // Number of bytes received
+    char rx_line_buffer[RX_LINE_BUFFER_SIZE]; // Buffer for received lines
+    uint8_t file_buffer[FILE_BUFFER_SIZE]; // Buffer for file data
+    size_t file_buffer_len; // Length of the file buffer
+    size_t content_length; // Length of the content received
+    int status_code; // HTTP status code
 } 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];
-extern size_t file_buffer_len;
-
-// 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.
+ * @return     FlipperHTTP context if the UART was initialized successfully, NULL otherwise.
  * @note       The received data will be handled asynchronously via the callback.
  */
-bool flipper_http_init(FlipperHTTP_Callback callback, void *context);
+FlipperHTTP* flipper_http_alloc();
 
-// Deinitialize UART
 /**
  * @brief      Deinitialize UART.
  * @return     void
+ * @param fhttp The FlipperHTTP context
  * @note       This function will stop the asynchronous RX, release the serial handle, and free the resources.
  */
-void flipper_http_deinit();
+void flipper_http_free(FlipperHTTP* fhttp);
 
-// 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.
+ * @brief      Append received data to a file.
+ * @return     true if the data was appended successfully, false otherwise.
+ * @param      data        The data to append to the file.
+ * @param      data_size   The size of the data to append.
+ * @param      start_new_file  Flag to indicate if a new file should be created.
+ * @param      file_path   The path to the file.
+ * @note       Make sure to initialize the file path before calling this function.
  */
-bool flipper_http_ping();
+bool flipper_http_append_to_file(
+    const void* data,
+    size_t data_size,
+    bool start_new_file,
+    char* file_path);
 
-// 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.
+ * @brief      Load data from a file.
+ * @return     The loaded data as a FuriString.
+ * @param      file_path The path to the file to load.
  */
-bool flipper_http_list_commands();
+FuriString* flipper_http_load_from_file(char* file_path);
 
-// 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.
+ * @brief      Load data from a file with a size limit.
+ * @return     The loaded data as a FuriString.
+ * @param      file_path The path to the file to load.
+ * @param      limit     The size limit for loading data.
  */
-bool flipper_http_led_on();
+FuriString* flipper_http_load_from_file_with_limit(char* file_path, size_t limit);
 
-// 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.
+ * @brief Perform a task while displaying a loading screen
+ * @param fhttp The FlipperHTTP context
+ * @param http_request The function to send the request
+ * @param parse_response The function to parse the response
+ * @param success_view_id The view ID to switch to on success
+ * @param failure_view_id The view ID to switch to on failure
+ * @param view_dispatcher The view dispatcher to use
+ * @return
  */
-bool flipper_http_led_off();
+void flipper_http_loading_task(
+    FlipperHTTP* fhttp,
+    bool (*http_request)(void),
+    bool (*parse_response)(void),
+    uint32_t success_view_id,
+    uint32_t failure_view_id,
+    ViewDispatcher** view_dispatcher);
 
-// Function to parse JSON data
 /**
  * @brief      Parse JSON data.
  * @return     true if the JSON data was parsed successfully, false otherwise.
+ * @param fhttp The FlipperHTTP context
  * @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);
+bool flipper_http_parse_json(FlipperHTTP* fhttp, 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 fhttp The FlipperHTTP context
  * @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();
+bool flipper_http_parse_json_array(
+    FlipperHTTP* fhttp,
+    const char* key,
+    int index,
+    const char* json_data);
 
-// 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.
+ * @brief Process requests and parse JSON data asynchronously
+ * @param fhttp The FlipperHTTP context
+ * @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_get_request(const char *url);
+bool flipper_http_process_response_async(
+    FlipperHTTP* fhttp,
+    bool (*http_request)(void),
+    bool (*parse_json)(void));
 
-// Function to send a GET request with headers
 /**
- * @brief      Send a GET request to the specified URL.
+ * @brief      Send a 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.
+ * @param      fhttp The FlipperHTTP context
+ * @param      method The HTTP method to use.
+ * @param      url  The URL to send the request to.
+ * @param      headers  The headers to send with the request.
+ * @param      payload  The data to send with the 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);
+bool flipper_http_request(
+    FlipperHTTP* fhttp,
+    HTTPMethod method,
+    const char* url,
+    const char* headers,
+    const char* payload);
 
-// Function to send a GET request with headers and return bytes
 /**
- * @brief      Send a GET request to the specified URL.
+ * @brief      Send a command to save WiFi settings.
  * @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.
+ * @param fhttp The FlipperHTTP context
  * @note       The received data will be handled asynchronously via the callback.
  */
-bool flipper_http_get_request_bytes(const char *url, const char *headers);
+bool flipper_http_save_wifi(FlipperHTTP* fhttp, const char* ssid, const char* password);
 
-// Function to send a POST request with headers
 /**
- * @brief      Send a POST request to the specified URL.
+ * @brief      Send a command.
  * @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.
+ * @param      fhttp The FlipperHTTP context
+ * @param      command The command to send.
  * @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);
+bool flipper_http_send_command(FlipperHTTP* fhttp, HTTPCommand command);
 
-// 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.
+ * @brief      Send data over UART with newline termination.
+ * @return     true if the data was sent successfully, false otherwise.
+ * @param fhttp The FlipperHTTP context
+ * @param      data  The data to send over UART.
+ * @note       The data will be sent over UART with a newline character appended.
  */
-bool flipper_http_post_request_bytes(const char *url, const char *headers, const char *payload);
+bool flipper_http_send_data(FlipperHTTP* fhttp, const char* data);
 
-// Function to send a PUT request with headers
 /**
- * @brief      Send a PUT request to the specified URL.
+ * @brief      Send a request to the specified URL to start a WebSocket connection.
  * @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.
+ * @param fhttp The FlipperHTTP context
+ * @param      url  The URL to send the WebSocket request to.
+ * @param port The port to connect to
+ * @param headers The headers to send with the WebSocket 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);
+bool flipper_http_websocket_start(
+    FlipperHTTP* fhttp,
+    const char* url,
+    uint16_t port,
+    const char* headers);
 
-// Function to send a DELETE request with headers
 /**
- * @brief      Send a DELETE request to the specified URL.
+ * @brief      Send a request to stop the WebSocket connection.
  * @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.
+ * @param fhttp The FlipperHTTP context
  * @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));
-
-/**
- * @brief Perform a task while displaying a loading screen
- * @param http_request The function to send the request
- * @param parse_response The function to parse the response
- * @param success_view_id The view ID to switch to on success
- * @param failure_view_id The view ID to switch to on failure
- * @param view_dispatcher The view dispatcher to use
- * @return
- */
-void flipper_http_loading_task(bool (*http_request)(void),
-                               bool (*parse_response)(void),
-                               uint32_t success_view_id,
-                               uint32_t failure_view_id,
-                               ViewDispatcher **view_dispatcher);
-
-#endif // FLIPPER_HTTP_H
+bool flipper_http_websocket_stop(FlipperHTTP* fhttp);

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů