web_crawler_uart.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <storage/storage.h>
  2. #include <furi_hal_gpio.h>
  3. #include <furi_hal_serial.h>
  4. #define UART_CH (FuriHalSerialIdUsart)
  5. #define BAUDRATE (115200)
  6. #define RX_BUF_SIZE 256
  7. #define SETTINGS_PATH STORAGE_EXT_PATH_PREFIX "/apps_data/web_crawler_app/settings.bin"
  8. #define SETTINGS_PATH_SD "/apps_data/web_crawler_app/settings.txt"
  9. #define TAG "WebCrawler"
  10. typedef struct
  11. {
  12. FuriStreamBuffer *uart_stream; // Stream buffer for UART communication
  13. FuriHalSerialHandle *serial_handle;
  14. } WebCrawlerUart;
  15. // Declare the UART instance
  16. WebCrawlerUart uart;
  17. static void uart_rx_callback(FuriHalSerialHandle *handle, FuriHalSerialRxEvent event, void *context)
  18. {
  19. UNUSED(context);
  20. if (event == FuriHalSerialRxEventData)
  21. {
  22. uint8_t data = furi_hal_serial_async_rx(handle); // Read the incoming byte
  23. furi_stream_buffer_send(uart.uart_stream, &data, 1, 0); // Send to stream buffer
  24. }
  25. }
  26. // Initialize UART
  27. void uart_init()
  28. {
  29. uart.uart_stream = furi_stream_buffer_alloc(RX_BUF_SIZE * 10, 1); // Increase buffer size if necessary
  30. uart.serial_handle = furi_hal_serial_control_acquire(UART_CH);
  31. furi_hal_serial_init(uart.serial_handle, BAUDRATE);
  32. furi_hal_serial_async_rx_start(uart.serial_handle, uart_rx_callback, NULL, false);
  33. FURI_LOG_I(TAG, "UART initialized.");
  34. }
  35. // Deinitialize UART
  36. void uart_deinit()
  37. {
  38. furi_hal_serial_async_rx_stop(uart.serial_handle);
  39. furi_hal_serial_deinit(uart.serial_handle);
  40. furi_hal_serial_control_release(uart.serial_handle);
  41. furi_stream_buffer_free(uart.uart_stream);
  42. }
  43. // Function to send settings via UART
  44. void send_settings_via_uart(const char *path, const char *ssid, const char *password)
  45. {
  46. char buffer[512];
  47. snprintf(buffer, sizeof(buffer), "{\"path\":\"%s\",\"ssid\":\"%s\",\"password\":\"%s\"}", path, ssid, password);
  48. size_t data_length = strlen(buffer);
  49. FURI_LOG_I(TAG, "Sending settings via UART: %s", buffer);
  50. furi_hal_serial_tx(uart.serial_handle, (uint8_t *)buffer, data_length);
  51. }
  52. bool first_run = true;
  53. // Function to read data from UART after sending settings and save to a file
  54. bool read_data_from_uart_and_save(Canvas *canvas) // Pass the canvas context
  55. {
  56. canvas_draw_str(canvas, 1, 35, "Initializing...");
  57. char line_buffer[RX_BUF_SIZE + 1];
  58. bool started = false;
  59. size_t total_received_data = 0;
  60. // Full path for the output file where we will save the received data
  61. const char *output_file_path = STORAGE_EXT_PATH_PREFIX "/apps_data/web_crawler_app/received_data.txt";
  62. // Ensure the directory exists
  63. char directory_path[256];
  64. snprintf(directory_path, sizeof(directory_path), STORAGE_EXT_PATH_PREFIX "/apps_data/web_crawler_app");
  65. Storage *storage = NULL;
  66. File *file = NULL;
  67. if (first_run)
  68. {
  69. first_run = false;
  70. return false;
  71. }
  72. FURI_LOG_I(TAG, "Waiting for data...");
  73. canvas_draw_str(canvas, 1, 50, "Saving data. Please wait");
  74. // Start reading data from UART line by line
  75. while (true)
  76. {
  77. size_t bytes_received = furi_stream_buffer_receive(uart.uart_stream, line_buffer, RX_BUF_SIZE, 2000); // Increase the timeout to 2000 ms
  78. if (bytes_received > 0)
  79. {
  80. line_buffer[bytes_received] = '\0'; // Null-terminate
  81. // Remove any carriage returns
  82. for (size_t i = 0; i < bytes_received; i++)
  83. {
  84. if (line_buffer[i] == '\r')
  85. {
  86. memmove(&line_buffer[i], &line_buffer[i + 1], bytes_received - i);
  87. bytes_received--;
  88. i--;
  89. }
  90. }
  91. // Check for the start marker
  92. if (!started && strstr(line_buffer, "[BIN/STARTED]") != NULL)
  93. {
  94. FURI_LOG_I(TAG, "Started receiving data... please wait and do not disconnect the device or leave this screen.");
  95. canvas_draw_str(canvas, 1, 60, "Receiving data...");
  96. started = true;
  97. // Now open the storage and file for writing since we've started receiving data
  98. storage = furi_record_open(RECORD_STORAGE);
  99. storage_common_mkdir(storage, directory_path); // Create directory if it doesn't exist
  100. file = storage_file_alloc(storage);
  101. if (!storage_file_open(file, output_file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS))
  102. {
  103. FURI_LOG_E(TAG, "Failed to open output file for writing.");
  104. canvas_draw_str(canvas, 1, 60, "Failed to open file");
  105. storage_file_free(file);
  106. furi_record_close(RECORD_STORAGE);
  107. return false;
  108. }
  109. continue; // Skip to the next iteration after opening the file
  110. }
  111. // Check for the finish marker
  112. if (started && strstr(line_buffer, "[BIN/FINISHED]") != NULL)
  113. {
  114. FURI_LOG_I(TAG, "Finished receiving data.");
  115. canvas_draw_str(canvas, 1, 70, "Finished GET request.");
  116. break; // End the loop once the finish marker is detected
  117. }
  118. // If the data transfer has started, save data to the file
  119. if (started && file)
  120. {
  121. storage_file_write(file, line_buffer, bytes_received);
  122. total_received_data += bytes_received;
  123. }
  124. }
  125. else
  126. {
  127. // Timeout or no data received
  128. FURI_LOG_E(TAG, "Timeout.");
  129. break;
  130. }
  131. }
  132. // Close the file and storage only if they were opened
  133. if (file)
  134. {
  135. storage_file_close(file);
  136. storage_file_free(file);
  137. }
  138. if (storage)
  139. {
  140. furi_record_close(RECORD_STORAGE);
  141. }
  142. FURI_LOG_I(TAG, "Data reception complete. Total bytes received: %zu", total_received_data);
  143. if (total_received_data > 0)
  144. {
  145. canvas_draw_str(canvas, 1, 70, "Complete!");
  146. return true;
  147. }
  148. else
  149. {
  150. return false;
  151. }
  152. }