Bläddra i källkod

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

Willy-JL 1 år sedan
förälder
incheckning
4c625f2ebd

+ 48 - 8
flip_wifi/callback/flip_wifi_callback.c

@@ -194,14 +194,25 @@ char* trim_whitespace(char* start, size_t* length) {
 }
 
 bool flip_wifi_handle_scan(FlipWiFiApp* app) {
-    if(fhttp.last_response == NULL || fhttp.last_response[0] == '\0') {
-        FURI_LOG_E(TAG, "Failed to receive WiFi scan");
+    // 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, "Failed to load received data from file.");
+        fhttp.state = ISSUE;
+        return false;
+    }
+    char* data_cstr = (char*)furi_string_get_cstr(scan_data);
+    if(data_cstr == NULL) {
+        FURI_LOG_E(TAG, "Failed to get C-string from FuriString.");
+        furi_string_free(scan_data);
+        fhttp.state = ISSUE;
+        free(data_cstr);
         return false;
     }
 
     uint32_t ssid_count = 0;
 
-    char* current_position = fhttp.last_response;
+    char* current_position = data_cstr;
     char* next_comma = NULL;
 
     // Manually split the string on commas
@@ -223,6 +234,8 @@ bool flip_wifi_handle_scan(FlipWiFiApp* app) {
         ssid_list[ssid_count] = malloc(trimmed_length + 1);
         if(ssid_list[ssid_count] == NULL) {
             FURI_LOG_E(TAG, "Memory allocation failed");
+            free(data_cstr);
+            furi_string_free(scan_data);
             return false;
         }
         strncpy(ssid_list[ssid_count], trim_start, trimmed_length);
@@ -275,7 +288,8 @@ bool flip_wifi_handle_scan(FlipWiFiApp* app) {
             callback_submenu_choices,
             app);
     }
-
+    free(data_cstr);
+    furi_string_free(scan_data);
     return true;
 }
 void callback_submenu_choices(void* context, uint32_t index) {
@@ -303,6 +317,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
         // scan for wifi
         if(!flipper_http_scan_wifi()) {
             FURI_LOG_E(TAG, "Failed to scan for WiFi");
+            fhttp.state = ISSUE;
             return;
         } else // start the async feed request
         {
@@ -315,18 +330,43 @@ void callback_submenu_choices(void* context, uint32_t index) {
         }
         furi_timer_stop(fhttp.get_timeout_timer);
         // set each SSID as a submenu item
-        if(fhttp.state != IDLE || fhttp.last_response == NULL) {
+        if(fhttp.state != IDLE) {
+            fhttp.state = ISSUE;
             FURI_LOG_E(TAG, "Failed to receive WiFi scan");
-            return;
+            popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
+            popup_set_text(
+                app->popup,
+                "Failed to scan...\nTry reconnecting the board!",
+                0,
+                40,
+                AlignLeft,
+                AlignTop);
+            view_set_previous_callback(popup_get_view(app->popup), callback_to_submenu_main);
+            popup_set_callback(app->popup, popup_callback_main);
+            // switch to the popup view
+            view_dispatcher_switch_to_view(app->view_dispatcher, FlipWiFiViewPopup);
         } else {
             submenu_reset(app->submenu_wifi_scan);
             submenu_set_header(app->submenu_wifi_scan, "WiFi Nearby");
             if(flip_wifi_handle_scan(app)) {
                 // switch to the submenu
                 view_dispatcher_switch_to_view(app->view_dispatcher, FlipWiFiViewSubmenuScan);
+            } else {
+                fhttp.state = ISSUE;
+                FURI_LOG_E(TAG, "Failed to handle WiFi scan");
+                popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
+                popup_set_text(
+                    app->popup,
+                    "Failed to scan...\nTry reconnecting the board!",
+                    0,
+                    40,
+                    AlignLeft,
+                    AlignTop);
+                view_set_previous_callback(popup_get_view(app->popup), callback_to_submenu_main);
+                popup_set_callback(app->popup, popup_callback_main);
+                // switch to the popup view
+                view_dispatcher_switch_to_view(app->view_dispatcher, FlipWiFiViewPopup);
             }
-
-            FURI_LOG_E(TAG, "Failed to handle WiFi scan");
             return;
         }
         break;

+ 106 - 48
flip_wifi/flipper_http/flipper_http.c

@@ -2,6 +2,7 @@
 FlipperHTTP fhttp;
 char rx_line_buffer[RX_LINE_BUFFER_SIZE];
 uint8_t file_buffer[FILE_BUFFER_SIZE];
+size_t file_buffer_len = 0;
 // Function to append received data to file
 // make sure to initialize the file path before calling this function
 bool flipper_http_append_to_file(
@@ -13,6 +14,15 @@ bool flipper_http_append_to_file(
     File* file = storage_file_alloc(storage);
 
     if(start_new_file) {
+        // Delete the file if it already exists
+        if(storage_file_exists(storage, file_path)) {
+            if(!storage_simply_remove_recursive(storage, file_path)) {
+                FURI_LOG_E(HTTP_TAG, "Failed to delete file: %s", file_path);
+                storage_file_free(file);
+                furi_record_close(RECORD_STORAGE);
+                return false;
+            }
+        }
         // Open the file in write mode
         if(!storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
             FURI_LOG_E(HTTP_TAG, "Failed to open file for writing: %s", file_path);
@@ -131,12 +141,13 @@ FuriString* flipper_http_load_from_file(char* file_path) {
 int32_t flipper_http_worker(void* context) {
     UNUSED(context);
     size_t rx_line_pos = 0;
-    static size_t file_buffer_len = 0;
 
     while(1) {
         uint32_t events = furi_thread_flags_wait(
             WorkerEvtStop | WorkerEvtRxDone, FuriFlagWaitAny, FuriWaitForever);
-        if(events & WorkerEvtStop) break;
+        if(events & WorkerEvtStop) {
+            break;
+        }
         if(events & WorkerEvtRxDone) {
             // Continuously read from the stream buffer until it's empty
             while(!furi_stream_buffer_is_empty(fhttp.flipper_http_stream)) {
@@ -156,10 +167,14 @@ int32_t flipper_http_worker(void* context) {
                     // Write to file if buffer is full
                     if(file_buffer_len >= FILE_BUFFER_SIZE) {
                         if(!flipper_http_append_to_file(
-                               file_buffer, file_buffer_len, false, fhttp.file_path)) {
+                               file_buffer,
+                               file_buffer_len,
+                               fhttp.just_started_bytes,
+                               fhttp.file_path)) {
                             FURI_LOG_E(HTTP_TAG, "Failed to append data to file");
                         }
                         file_buffer_len = 0;
+                        fhttp.just_started_bytes = false;
                     }
                 }
 
@@ -182,36 +197,6 @@ int32_t flipper_http_worker(void* context) {
         }
     }
 
-    if(fhttp.save_bytes) {
-        // Write the remaining data to the file
-        if(file_buffer_len > 0) {
-            if(!flipper_http_append_to_file(file_buffer, file_buffer_len, false, fhttp.file_path)) {
-                FURI_LOG_E(HTTP_TAG, "Failed to append remaining data to file");
-            }
-        }
-    }
-
-    // remove [POST/END] and/or [GET/END] from the file
-    if(fhttp.save_bytes) {
-        char* end = NULL;
-        if((end = strstr(fhttp.file_path, "[POST/END]")) != NULL) {
-            *end = '\0';
-        } else if((end = strstr(fhttp.file_path, "[GET/END]")) != NULL) {
-            *end = '\0';
-        }
-    }
-
-    // remove newline from the from the end of the file
-    if(fhttp.save_bytes) {
-        char* end = NULL;
-        if((end = strstr(fhttp.file_path, "\n")) != NULL) {
-            *end = '\0';
-        }
-    }
-
-    // Reset the file buffer length
-    file_buffer_len = 0;
-
     return 0;
 }
 // Timer callback function
@@ -418,13 +403,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 > 512) { // Ensure buffer size is sufficient
+    if(send_length > 256) { // Ensure buffer size is sufficient
         FURI_LOG_E("FlipperHTTP", "Data too long to send over FHTTP.");
         return false;
     }
 
-    char send_buffer[513]; // 512 + 1 for safety
-    strncpy(send_buffer, data, 512);
+    char send_buffer[257]; // 256 + 1 for safety
+    strncpy(send_buffer, data, 256);
     send_buffer[data_length] = '\n'; // Append newline
     send_buffer[data_length + 1] = '\0'; // Null-terminate
 
@@ -440,7 +425,7 @@ bool flipper_http_send_data(const char* data) {
 
     // Uncomment below line to log the data sent over UART
     // FURI_LOG_I("FlipperHTTP", "Sent data over UART: %s", send_buffer);
-    fhttp.state = IDLE;
+    // fhttp.state = IDLE;
     return true;
 }
 
@@ -590,11 +575,18 @@ bool flipper_http_parse_json_array(const char* key, int index, const char* json_
  * @note       The received data will be handled asynchronously via the callback.
  */
 bool flipper_http_scan_wifi() {
-    const char* command = "[WIFI/SCAN]";
-    if(!flipper_http_send_data(command)) {
+    if(!flipper_http_send_data("[WIFI/SCAN]")) {
         FURI_LOG_E("FlipperHTTP", "Failed to send WiFi scan command.");
         return false;
     }
+    // custom for FlipWiFi app
+    fhttp.just_started_get = true;
+    snprintf(
+        fhttp.file_path,
+        sizeof(fhttp.file_path),
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_wifi/scan.txt");
+
+    fhttp.save_received_data = true;
 
     // The response will be handled asynchronously via the callback
     return true;
@@ -635,8 +627,7 @@ bool flipper_http_save_wifi(const char* ssid, const char* password) {
  * @note       The received data will be handled asynchronously via the callback.
  */
 bool flipper_http_ip_address() {
-    const char* command = "[IP/ADDRESS]";
-    if(!flipper_http_send_data(command)) {
+    if(!flipper_http_send_data("[IP/ADDRESS]")) {
         FURI_LOG_E("FlipperHTTP", "Failed to send IP address command.");
         return false;
     }
@@ -669,8 +660,7 @@ bool flipper_http_ip_wifi() {
  * @note       The received data will be handled asynchronously via the callback.
  */
 bool flipper_http_disconnect_wifi() {
-    const char* command = "[WIFI/DISCONNECT]";
-    if(!flipper_http_send_data(command)) {
+    if(!flipper_http_send_data("[WIFI/DISCONNECT]")) {
         FURI_LOG_E("FlipperHTTP", "Failed to send WiFi disconnect command.");
         return false;
     }
@@ -686,8 +676,7 @@ bool flipper_http_disconnect_wifi() {
  * @note       The received data will be handled asynchronously via the callback.
  */
 bool flipper_http_connect_wifi() {
-    const char* command = "[WIFI/CONNECT]";
-    if(!flipper_http_send_data(command)) {
+    if(!flipper_http_send_data("[WIFI/CONNECT]")) {
         FURI_LOG_E("FlipperHTTP", "Failed to send WiFi connect command.");
         return false;
     }
@@ -742,7 +731,7 @@ bool flipper_http_get_request_with_headers(const char* url, const char* headers)
     }
 
     // Prepare GET request command with headers
-    char command[512];
+    char command[256];
     int ret = snprintf(
         command, sizeof(command), "[GET/HTTP]{\"url\":\"%s\",\"headers\":%s}", url, headers);
     if(ret < 0 || ret >= (int)sizeof(command)) {
@@ -993,6 +982,17 @@ void flipper_http_rx_callback(const char* line, void* context) {
     // Uncomment below line to log the data received over UART
     // FURI_LOG_I(HTTP_TAG, "Received UART line: %s", line);
 
+    // custom function to FlipWiFi
+    if(fhttp.save_received_data) {
+        if(!flipper_http_append_to_file(
+               line, strlen(line), fhttp.just_started_get, fhttp.file_path)) {
+            FURI_LOG_E(HTTP_TAG, "Failed to append data to file.");
+            fhttp.just_started_get = false;
+            fhttp.state = ISSUE;
+            return;
+        }
+    }
+
     // Check if we've started receiving data from a GET request
     if(fhttp.started_receiving_get) {
         // Restart the timeout timer each time new data is received
@@ -1006,8 +1006,35 @@ void flipper_http_rx_callback(const char* line, void* context) {
             fhttp.just_started_get = false;
             fhttp.state = IDLE;
             fhttp.save_bytes = false;
-            fhttp.is_bytes_request = false;
             fhttp.save_received_data = false;
+
+            if(fhttp.is_bytes_request) {
+                // Search for the binary marker `[GET/END]` in the file buffer
+                const char marker[] = "[GET/END]";
+                const size_t marker_len = sizeof(marker) - 1; // Exclude null terminator
+
+                for(size_t i = 0; i <= file_buffer_len - marker_len; i++) {
+                    // Check if the marker is found
+                    if(memcmp(&file_buffer[i], marker, marker_len) == 0) {
+                        // Remove the marker by shifting the remaining data left
+                        size_t remaining_len = file_buffer_len - (i + marker_len);
+                        memmove(&file_buffer[i], &file_buffer[i + marker_len], remaining_len);
+                        file_buffer_len -= marker_len;
+                        break;
+                    }
+                }
+
+                // If there is data left in the buffer, append it to the file
+                if(file_buffer_len > 0) {
+                    if(!flipper_http_append_to_file(
+                           file_buffer, file_buffer_len, false, fhttp.file_path)) {
+                        FURI_LOG_E(HTTP_TAG, "Failed to append data to file.");
+                    }
+                    file_buffer_len = 0;
+                }
+            }
+
+            fhttp.is_bytes_request = false;
             return;
         }
 
@@ -1041,8 +1068,35 @@ void flipper_http_rx_callback(const char* line, void* context) {
             fhttp.just_started_post = false;
             fhttp.state = IDLE;
             fhttp.save_bytes = false;
-            fhttp.is_bytes_request = false;
             fhttp.save_received_data = false;
+
+            if(fhttp.is_bytes_request) {
+                // Search for the binary marker `[POST/END]` in the file buffer
+                const char marker[] = "[POST/END]";
+                const size_t marker_len = sizeof(marker) - 1; // Exclude null terminator
+
+                for(size_t i = 0; i <= file_buffer_len - marker_len; i++) {
+                    // Check if the marker is found
+                    if(memcmp(&file_buffer[i], marker, marker_len) == 0) {
+                        // Remove the marker by shifting the remaining data left
+                        size_t remaining_len = file_buffer_len - (i + marker_len);
+                        memmove(&file_buffer[i], &file_buffer[i + marker_len], remaining_len);
+                        file_buffer_len -= marker_len;
+                        break;
+                    }
+                }
+
+                // If there is data left in the buffer, append it to the file
+                if(file_buffer_len > 0) {
+                    if(!flipper_http_append_to_file(
+                           file_buffer, file_buffer_len, false, fhttp.file_path)) {
+                        FURI_LOG_E(HTTP_TAG, "Failed to append data to file.");
+                    }
+                    file_buffer_len = 0;
+                }
+            }
+
+            fhttp.is_bytes_request = false;
             return;
         }
 
@@ -1149,6 +1203,8 @@ void flipper_http_rx_callback(const char* line, void* context) {
         fhttp.state = RECEIVING;
         // for GET request, save data only if it's a bytes request
         fhttp.save_bytes = fhttp.is_bytes_request;
+        fhttp.just_started_bytes = true;
+        file_buffer_len = 0;
         return;
     } else if(strstr(line, "[POST/SUCCESS]") != NULL) {
         FURI_LOG_I(HTTP_TAG, "POST request succeeded.");
@@ -1157,6 +1213,8 @@ void flipper_http_rx_callback(const char* line, void* context) {
         fhttp.state = RECEIVING;
         // for POST request, save data only if it's a bytes request
         fhttp.save_bytes = fhttp.is_bytes_request;
+        fhttp.just_started_bytes = true;
+        file_buffer_len = 0;
         return;
     } else if(strstr(line, "[PUT/SUCCESS]") != NULL) {
         FURI_LOG_I(HTTP_TAG, "PUT request succeeded.");

+ 3 - 0
flip_wifi/flipper_http/flipper_http.h

@@ -74,12 +74,15 @@ typedef struct {
     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
 } 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