camera_suite_view_wifi_camera.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "../camera_suite.h"
  2. #include "camera_suite_view_wifi_camera.h"
  3. #include "../helpers/camera_suite_haptic.h"
  4. #include "../helpers/camera_suite_led.h"
  5. #include "../helpers/camera_suite_speaker.h"
  6. #include "../helpers/camera_suite_custom_event.h"
  7. // #include "../helpers/camera_suite_uart.h"
  8. static void camera_suite_view_wifi_camera_draw(Canvas* canvas, void* wifi_model) {
  9. furi_assert(canvas);
  10. furi_assert(wifi_model);
  11. UartDumpModel* model = wifi_model;
  12. canvas_clear(canvas);
  13. canvas_set_color(canvas, ColorBlack);
  14. canvas_set_font(canvas, FontSecondary);
  15. canvas_draw_frame(canvas, 0, 0, FLIPPER_SCREEN_HEIGHT, FLIPPER_SCREEN_HEIGHT);
  16. canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, "Starting WiFi Stream at:");
  17. // Draw log from camera.
  18. canvas_draw_str_aligned(canvas, 3, 13, AlignLeft, AlignTop, furi_string_get_cstr(model->log));
  19. }
  20. static int32_t camera_suite_wifi_camera_worker(void* wifi_view_instance) {
  21. furi_assert(wifi_view_instance);
  22. CameraSuiteViewWiFiCamera* instance = wifi_view_instance;
  23. CameraSuite* app_instance = instance->context;
  24. while(1) {
  25. uint32_t events =
  26. furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever);
  27. // Check if an error occurred.
  28. furi_check((events & FuriFlagError) == 0);
  29. // Check if the thread should stop.
  30. if(events & WorkerEventStop) {
  31. break;
  32. } else if(events & WorkerEventRx) {
  33. size_t length = 0;
  34. do {
  35. size_t buffer_size = 320;
  36. uint8_t data[buffer_size];
  37. length = furi_stream_buffer_receive(app_instance->rx_stream, data, buffer_size, 0);
  38. if(length > 0) {
  39. data[length] = '\0';
  40. with_view_model(
  41. instance->view,
  42. UartDumpModel * model,
  43. {
  44. furi_string_cat_printf(model->log, "%s", data);
  45. // Truncate if too long.
  46. model->log_strlen += length;
  47. if(model->log_strlen >= 4096 - 1) {
  48. furi_string_right(model->log, model->log_strlen / 2);
  49. model->log_strlen = furi_string_size(model->log) + length;
  50. }
  51. },
  52. true);
  53. }
  54. } while(length > 0);
  55. with_view_model(
  56. instance->view, UartDumpModel * model, { UNUSED(model); }, true);
  57. }
  58. }
  59. return 0;
  60. }
  61. static bool
  62. camera_suite_view_wifi_camera_input(InputEvent* input_event, void* wifi_view_instance) {
  63. furi_assert(wifi_view_instance);
  64. furi_assert(input_event);
  65. CameraSuiteViewWiFiCamera* instance = wifi_view_instance;
  66. CameraSuite* app_instance = instance->context;
  67. uint8_t data[1];
  68. if(input_event->type == InputTypeRelease) {
  69. switch(input_event->key) {
  70. default:
  71. with_view_model(
  72. instance->view,
  73. UartDumpModel * model,
  74. {
  75. UNUSED(model);
  76. // Stop all sounds, reset the LED.
  77. camera_suite_play_bad_bump(instance->context);
  78. camera_suite_stop_all_sound(instance->context);
  79. camera_suite_led_set_rgb(instance->context, 0, 0, 0);
  80. },
  81. true);
  82. break;
  83. }
  84. } else if(input_event->type == InputTypePress) {
  85. switch(input_event->key) {
  86. case InputKeyBack: {
  87. with_view_model(
  88. instance->view,
  89. UartDumpModel * model,
  90. {
  91. UNUSED(model);
  92. // Stop camera WiFi stream.
  93. data[0] = 'w';
  94. furi_hal_serial_tx(app_instance->serial_handle, data, 1);
  95. furi_delay_ms(50);
  96. // Go back to the main menu.
  97. instance->callback(
  98. CameraSuiteCustomEventSceneWiFiCameraBack, instance->context);
  99. },
  100. true);
  101. break;
  102. }
  103. case InputKeyLeft:
  104. case InputKeyRight:
  105. case InputKeyUp:
  106. case InputKeyDown:
  107. case InputKeyOk:
  108. case InputKeyMAX:
  109. default: {
  110. break;
  111. }
  112. }
  113. }
  114. return false;
  115. }
  116. static void camera_suite_view_wifi_camera_exit(void* wifi_view_instance) {
  117. UNUSED(wifi_view_instance);
  118. }
  119. static void camera_suite_view_wifi_camera_model_init(UartDumpModel* const model) {
  120. model->log = furi_string_alloc();
  121. furi_string_reserve(model->log, 4096);
  122. }
  123. static void camera_suite_view_wifi_camera_enter(void* wifi_view_instance) {
  124. furi_assert(wifi_view_instance);
  125. CameraSuiteViewWiFiCamera* instance = wifi_view_instance;
  126. CameraSuite* app_instance = instance->context;
  127. // Start wifi camera stream.
  128. uint8_t data[1] = {'W'};
  129. furi_hal_serial_tx(app_instance->serial_handle, data, 1);
  130. furi_delay_ms(50);
  131. with_view_model(
  132. instance->view,
  133. UartDumpModel * model,
  134. { camera_suite_view_wifi_camera_model_init(model); },
  135. true);
  136. }
  137. static void wifi_camera_callback(
  138. FuriHalSerialHandle* handle,
  139. FuriHalSerialRxEvent event,
  140. void* wifi_view_instance) {
  141. furi_assert(handle);
  142. furi_assert(wifi_view_instance);
  143. CameraSuiteViewWiFiCamera* instance = wifi_view_instance;
  144. CameraSuite* app_instance = instance->context;
  145. if(event == FuriHalSerialRxEventData) {
  146. uint8_t data = furi_hal_serial_async_rx(handle);
  147. furi_stream_buffer_send(app_instance->rx_stream, &data, 1, 0);
  148. furi_thread_flags_set(furi_thread_get_id(app_instance->worker_thread), WorkerEventRx);
  149. }
  150. }
  151. CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc() {
  152. CameraSuiteViewWiFiCamera* instance = malloc(sizeof(CameraSuiteViewWiFiCamera));
  153. // Allocate the view object
  154. instance->view = view_alloc();
  155. // Allocate model
  156. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(UartDumpModel));
  157. // Set context for the view
  158. view_set_context(instance->view, instance);
  159. // Set draw callback
  160. view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_wifi_camera_draw);
  161. // Set input callback
  162. view_set_input_callback(instance->view, camera_suite_view_wifi_camera_input);
  163. // Set enter callback
  164. view_set_enter_callback(instance->view, camera_suite_view_wifi_camera_enter);
  165. // Set exit callback
  166. view_set_exit_callback(instance->view, camera_suite_view_wifi_camera_exit);
  167. // Allocate the UART worker thread for the camera.
  168. // CameraSuite* app_instance = instance->context;
  169. // camera_suite_uart_alloc(app_instance, wifi_camera_callback);
  170. with_view_model(
  171. instance->view,
  172. UartDumpModel * model,
  173. { camera_suite_view_wifi_camera_model_init(model); },
  174. true);
  175. return instance;
  176. }
  177. void camera_suite_view_wifi_camera_free(CameraSuiteViewWiFiCamera* instance) {
  178. furi_assert(instance);
  179. CameraSuite* app_instance = instance->context;
  180. // Free the worker thread.
  181. furi_thread_flags_set(furi_thread_get_id(app_instance->worker_thread), WorkerEventStop);
  182. furi_thread_join(app_instance->worker_thread);
  183. furi_thread_free(app_instance->worker_thread);
  184. // Free the allocated stream buffer.
  185. furi_stream_buffer_free(app_instance->rx_stream);
  186. // camera_suite_uart_free(app_instance);
  187. with_view_model(
  188. instance->view, UartDumpModel * model, { furi_string_free(model->log); }, true);
  189. view_free(instance->view);
  190. free(instance);
  191. }
  192. View* camera_suite_view_wifi_camera_get_view(CameraSuiteViewWiFiCamera* instance) {
  193. furi_assert(instance);
  194. return instance->view;
  195. }
  196. void camera_suite_view_wifi_camera_set_callback(
  197. CameraSuiteViewWiFiCamera* instance,
  198. CameraSuiteViewWiFiCameraCallback callback,
  199. void* context) {
  200. furi_assert(instance);
  201. furi_assert(callback);
  202. instance->callback = callback;
  203. instance->context = context;
  204. }