Cody Tolene пре 2 година
родитељ
комит
12b84150df

+ 15 - 14
views/camera_suite_view_camera.c

@@ -469,10 +469,10 @@ static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* cont
     CameraSuiteViewCamera* instance = context;
 
     // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the
-    // `rx_stream` and set the `WorkerEventRx` flag.
+    // `camera_rx_stream` and set the `WorkerEventRx` flag.
     if(uartIrqEvent == UartIrqEventRXNE) {
-        furi_stream_buffer_send(instance->rx_stream, &data, 1, 0);
-        furi_thread_flags_set(furi_thread_get_id(instance->worker_thread), WorkerEventRx);
+        furi_stream_buffer_send(instance->camera_rx_stream, &data, 1, 0);
+        furi_thread_flags_set(furi_thread_get_id(instance->camera_worker_thread), WorkerEventRx);
     }
 }
 
@@ -524,7 +524,7 @@ static void process_ringbuffer(UartDumpModel* model, uint8_t const byte) {
     }
 }
 
-static int32_t camera_worker(void* context) {
+static int32_t camera_suite_camera_worker(void* context) {
     furi_assert(context);
 
     CameraSuiteViewCamera* instance = context;
@@ -532,7 +532,7 @@ static int32_t camera_worker(void* context) {
     while(1) {
         // Wait for any event on the worker thread.
         uint32_t events =
-            furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever);
+            furi_thread_flags_wait(CAMERA_WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever);
 
         // Check if an error occurred.
         furi_check((events & FuriFlagError) == 0);
@@ -545,12 +545,12 @@ static int32_t camera_worker(void* context) {
             // Read all available data from the stream buffer.
             do {
                 // Read up to 64 bytes from the stream buffer.
-                size_t intended_data_size = 64;
+                size_t buffer_size = 64;
                 // Allocate a buffer for the data.
-                uint8_t data[intended_data_size];
+                uint8_t data[buffer_size];
                 // Read the data from the stream buffer.
                 length =
-                    furi_stream_buffer_receive(instance->rx_stream, data, intended_data_size, 0);
+                    furi_stream_buffer_receive(instance->camera_rx_stream, data, buffer_size, 0);
                 if(length > 0) {
                     with_view_model(
                         instance->view,
@@ -581,7 +581,7 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() {
     instance->view = view_alloc();
 
     // Allocate a stream buffer
-    instance->rx_stream = furi_stream_buffer_alloc(2048, 1);
+    instance->camera_rx_stream = furi_stream_buffer_alloc(2048, 1);
 
     // Allocate model
     view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(UartDumpModel));
@@ -602,9 +602,10 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() {
     view_set_exit_callback(instance->view, camera_suite_view_camera_exit);
 
     // Allocate a thread for this camera to run on.
-    FuriThread* thread = furi_thread_alloc_ex("UsbUartWorker", 2048, camera_worker, instance);
-    instance->worker_thread = thread;
-    furi_thread_start(instance->worker_thread);
+    FuriThread* thread = furi_thread_alloc_ex(
+        "Camera_Suite_Camera_Rx_Thread", 2048, camera_suite_camera_worker, instance);
+    instance->camera_worker_thread = thread;
+    furi_thread_start(instance->camera_worker_thread);
 
     // Disable console.
     furi_hal_console_disable();
@@ -625,10 +626,10 @@ void camera_suite_view_camera_free(CameraSuiteViewCamera* instance) {
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
 
     // Free the worker thread.
-    furi_thread_free(instance->worker_thread);
+    furi_thread_free(instance->camera_worker_thread);
 
     // Free the allocated stream buffer.
-    furi_stream_buffer_free(instance->rx_stream);
+    furi_stream_buffer_free(instance->camera_rx_stream);
 
     // Re-enable the console.
     // furi_hal_console_enable();

+ 3 - 3
views/camera_suite_view_camera.h

@@ -39,15 +39,15 @@ typedef enum {
     WorkerEventRx = (1 << 2),
 } WorkerEventFlags;
 
-#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
+#define CAMERA_WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
 
 // Forward declaration
 typedef void (*CameraSuiteViewCameraCallback)(CameraSuiteCustomEvent event, void* context);
 
 typedef struct CameraSuiteViewCamera {
     CameraSuiteViewCameraCallback callback;
-    FuriStreamBuffer* rx_stream;
-    FuriThread* worker_thread;
+    FuriStreamBuffer* camera_rx_stream;
+    FuriThread* camera_worker_thread;
     NotificationApp* notification;
     View* view;
     void* context;

+ 120 - 6
views/camera_suite_view_wifi_camera.c

@@ -12,11 +12,66 @@ static void camera_suite_view_wifi_camera_draw(Canvas* canvas, void* model) {
     furi_assert(canvas);
     furi_assert(model);
 
-    // Clear the screen.
-    canvas_set_color(canvas, ColorBlack);
+    CameraSuiteViewWiFiCameraModel* instance = model;
 
-    // Draw a frame.
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_set_font(canvas, FontSecondary);
     canvas_draw_frame(canvas, 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
+
+    canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, "Starting WiFi Stream at:");
+    canvas_draw_str_aligned(
+        canvas, 3, 13, AlignLeft, AlignTop, furi_string_get_cstr(instance->log));
+}
+
+static int32_t camera_suite_wifi_camera_worker(void* context) {
+    furi_assert(context);
+
+    CameraSuiteViewWiFiCamera* instance = context;
+
+    while(1) {
+        uint32_t events =
+            furi_thread_flags_wait(WIFI_WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever);
+
+        // Check if an error occurred.
+        furi_check((events & FuriFlagError) == 0);
+
+        // Check if the thread should stop.
+        if(events & WorkerEventStop) {
+            break;
+        } else if(events & WorkerEventRx) {
+            size_t length = 0;
+            do {
+                size_t buffer_size = 320;
+                uint8_t data[buffer_size];
+                length =
+                    furi_stream_buffer_receive(instance->wifi_rx_stream, data, buffer_size, 0);
+                if(length > 0) {
+                    data[length] = '\0';
+
+                    with_view_model(
+                        instance->view,
+                        CameraSuiteViewWiFiCameraModel * model,
+                        {
+                            furi_string_cat_printf(model->log, "%s", data);
+
+                            // Truncate if too long.
+                            model->log_strlen += length;
+                            if(model->log_strlen >= 4096 - 1) {
+                                furi_string_right(model->log, model->log_strlen / 2);
+                                model->log_strlen = furi_string_size(model->log) + length;
+                            }
+                        },
+                        true);
+                }
+            } while(length > 0);
+
+            with_view_model(
+                instance->view, CameraSuiteViewWiFiCameraModel * model, { UNUSED(model); }, true);
+        }
+    }
+
+    return 0;
 }
 
 static bool camera_suite_view_wifi_camera_input(InputEvent* event, void* context) {
@@ -78,11 +133,44 @@ static void camera_suite_view_wifi_camera_exit(void* context) {
     furi_assert(context);
 }
 
+static void camera_suite_view_wifi_camera_model_init(CameraSuiteViewWiFiCameraModel* const model) {
+    model->log = furi_string_alloc();
+    furi_string_reserve(model->log, 4096);
+
+    // Set the initial log message.
+    // furi_string_printf(model->log, "Starting WiFi Camera Stream...:\n");
+}
+
 static void camera_suite_view_wifi_camera_enter(void* context) {
-    UNUSED(context);
+    furi_assert(context);
+
+    // Get the camera suite instance context.
+    CameraSuiteViewWiFiCamera* instance = (CameraSuiteViewWiFiCamera*)context;
 
     // Start wifi camera stream.
     furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'W'}, 1);
+
+    with_view_model(
+        instance->view,
+        CameraSuiteViewWiFiCameraModel * model,
+        { camera_suite_view_wifi_camera_model_init(model); },
+        true);
+}
+
+static void wifi_camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* context) {
+    furi_assert(uartIrqEvent);
+    furi_assert(data);
+    furi_assert(context);
+
+    // Cast `context` to `CameraSuiteViewWiFiCamera*` and store it in `instance`.
+    CameraSuiteViewWiFiCamera* instance = context;
+
+    // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the
+    // `wifi_rx_stream` and set the `WorkerEventRx` flag.
+    if(uartIrqEvent == UartIrqEventRXNE) {
+        furi_stream_buffer_send(instance->wifi_rx_stream, &data, 1, 0);
+        furi_thread_flags_set(furi_thread_get_id(instance->wifi_worker_thread), WorkerEventRx);
+    }
 }
 
 CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc() {
@@ -111,12 +199,30 @@ CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc() {
     // Set exit callback
     view_set_exit_callback(instance->view, camera_suite_view_wifi_camera_exit);
 
+    // Allocate a stream buffer
+    instance->wifi_rx_stream = furi_stream_buffer_alloc(1024, 1);
+
+    // Allocate a thread for this camera to run on.
+    FuriThread* thread = furi_thread_alloc_ex(
+        "Camera_Suite_WiFi_Rx_Thread", 1024, camera_suite_wifi_camera_worker, instance);
+    instance->wifi_worker_thread = thread;
+    furi_thread_start(instance->wifi_worker_thread);
+
     // Disable console.
     furi_hal_console_disable();
 
     // 115200 is the default baud rate for the ESP32-CAM.
     furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
 
+    // Enable UART1 and set the IRQ callback.
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, wifi_camera_on_irq_cb, instance);
+
+    with_view_model(
+        instance->view,
+        CameraSuiteViewWiFiCameraModel * model,
+        { camera_suite_view_wifi_camera_model_init(model); },
+        true);
+
     return instance;
 }
 
@@ -126,12 +232,20 @@ void camera_suite_view_wifi_camera_free(CameraSuiteViewWiFiCamera* instance) {
     // Remove the IRQ callback.
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
 
+    // Free the worker thread.
+    furi_thread_free(instance->wifi_worker_thread);
+
+    // Free the allocated stream buffer.
+    furi_stream_buffer_free(instance->wifi_rx_stream);
+
     // Re-enable the console.
     furi_hal_console_enable();
 
     with_view_model(
-        instance->view, CameraSuiteViewWiFiCameraModel * model, { UNUSED(model); }, true);
-
+        instance->view,
+        CameraSuiteViewWiFiCameraModel * model,
+        { furi_string_free(model->log); },
+        true);
     view_free(instance->view);
     free(instance);
 }

+ 9 - 2
views/camera_suite_view_wifi_camera.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#include <gui/modules/text_box.h>
+
 #include <furi.h>
 #include <furi_hal.h>
 #include <furi_hal_console.h>
@@ -17,17 +19,22 @@
 
 #include "../helpers/camera_suite_custom_event.h"
 
+typedef void (*CameraSuiteViewWiFiCameraCallback)(CameraSuiteCustomEvent event, void* context);
+
 typedef struct CameraSuiteViewWiFiCamera {
     CameraSuiteViewCameraCallback callback;
+    FuriStreamBuffer* wifi_rx_stream;
+    FuriThread* wifi_worker_thread;
     View* view;
     void* context;
 } CameraSuiteViewWiFiCamera;
 
 typedef struct {
-    int some_value;
+    FuriString* log;
+    size_t log_strlen;
 } CameraSuiteViewWiFiCameraModel;
 
-typedef void (*CameraSuiteViewWiFiCameraCallback)(CameraSuiteCustomEvent event, void* context);
+#define WIFI_WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
 
 CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc();