uhf_app.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "uhf_app_i.h"
  2. static const char* uhf_file_header = "Flipper UHF device";
  3. static const uint32_t uhf_file_version = 1;
  4. char* convertToHexString(const uint8_t* array, size_t length) {
  5. if(array == NULL || length == 0) {
  6. return NULL;
  7. }
  8. // Each byte takes 3 characters in the hex representation (2 characters + space), plus 1 for the null terminator
  9. size_t hexLength = (length * 3) + 1;
  10. char* hexArray = (char*)malloc(hexLength * sizeof(char));
  11. if(hexArray == NULL) {
  12. return NULL;
  13. }
  14. size_t index = 0;
  15. for(size_t i = 0; i < length; i++) {
  16. index += snprintf(&hexArray[index], hexLength - index, "%02x ", array[i]);
  17. }
  18. hexArray[hexLength - 1] = '\0';
  19. return hexArray;
  20. }
  21. bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) {
  22. if(!storage_dir_exists(storage, UHF_APPS_DATA_FOLDER)) {
  23. storage_simply_mkdir(storage, UHF_APPS_DATA_FOLDER);
  24. }
  25. if(!storage_dir_exists(storage, UHF_APPS_STORAGE_FOLDER)) {
  26. storage_simply_mkdir(storage, UHF_APPS_STORAGE_FOLDER);
  27. }
  28. FlipperFormat* file = flipper_format_file_alloc(storage);
  29. FuriString* temp_str = furi_string_alloc();
  30. // set file name
  31. furi_string_cat_printf(
  32. temp_str, "%s/%s%s", UHF_APPS_STORAGE_FOLDER, filename, UHF_FILE_EXTENSION);
  33. // open file
  34. if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) return false;
  35. // write header
  36. if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false;
  37. // write epc bank
  38. if(!flipper_format_write_hex(
  39. file, "EPC", uhf_response_data->data->data, uhf_response_data->data->length))
  40. return false;
  41. furi_string_free(temp_str);
  42. flipper_format_free(file);
  43. return true;
  44. }
  45. bool uhf_custom_event_callback(void* ctx, uint32_t event) {
  46. furi_assert(ctx);
  47. UHFApp* uhf_app = ctx;
  48. return scene_manager_handle_custom_event(uhf_app->scene_manager, event);
  49. }
  50. bool uhf_back_event_callback(void* ctx) {
  51. furi_assert(ctx);
  52. UHFApp* uhf_app = ctx;
  53. return scene_manager_handle_back_event(uhf_app->scene_manager);
  54. }
  55. void uhf_tick_event_callback(void* ctx) {
  56. furi_assert(ctx);
  57. UHFApp* uhf_app = ctx;
  58. scene_manager_handle_tick_event(uhf_app->scene_manager);
  59. }
  60. UHFApp* uhf_alloc() {
  61. UHFApp* uhf_app = (UHFApp*)malloc(sizeof(UHFApp));
  62. uhf_app->worker = (UHFWorker*)uhf_worker_alloc();
  63. uhf_app->view_dispatcher = view_dispatcher_alloc();
  64. uhf_app->scene_manager = scene_manager_alloc(&uhf_scene_handlers, uhf_app);
  65. view_dispatcher_enable_queue(uhf_app->view_dispatcher);
  66. view_dispatcher_set_event_callback_context(uhf_app->view_dispatcher, uhf_app);
  67. view_dispatcher_set_custom_event_callback(uhf_app->view_dispatcher, uhf_custom_event_callback);
  68. view_dispatcher_set_navigation_event_callback(
  69. uhf_app->view_dispatcher, uhf_back_event_callback);
  70. view_dispatcher_set_tick_event_callback(
  71. uhf_app->view_dispatcher, uhf_tick_event_callback, 100);
  72. // Open GUI record
  73. uhf_app->gui = furi_record_open(RECORD_GUI);
  74. view_dispatcher_attach_to_gui(
  75. uhf_app->view_dispatcher, uhf_app->gui, ViewDispatcherTypeFullscreen);
  76. // Storage
  77. uhf_app->storage = furi_record_open(RECORD_STORAGE);
  78. // Open Notification record
  79. uhf_app->notifications = furi_record_open(RECORD_NOTIFICATION);
  80. // Submenu
  81. uhf_app->submenu = submenu_alloc();
  82. view_dispatcher_add_view(
  83. uhf_app->view_dispatcher, UHFViewMenu, submenu_get_view(uhf_app->submenu));
  84. // Popup
  85. uhf_app->popup = popup_alloc();
  86. view_dispatcher_add_view(
  87. uhf_app->view_dispatcher, UHFViewPopup, popup_get_view(uhf_app->popup));
  88. // Loading
  89. uhf_app->loading = loading_alloc();
  90. view_dispatcher_add_view(
  91. uhf_app->view_dispatcher, UHFViewLoading, loading_get_view(uhf_app->loading));
  92. // Text Input
  93. uhf_app->text_input = text_input_alloc();
  94. view_dispatcher_add_view(
  95. uhf_app->view_dispatcher, UHFViewTextInput, text_input_get_view(uhf_app->text_input));
  96. // Custom Widget
  97. uhf_app->widget = widget_alloc();
  98. view_dispatcher_add_view(
  99. uhf_app->view_dispatcher, UHFViewWidget, widget_get_view(uhf_app->widget));
  100. return uhf_app;
  101. }
  102. void uhf_free(UHFApp* uhf_app) {
  103. furi_assert(uhf_app);
  104. // Submenu
  105. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewMenu);
  106. submenu_free(uhf_app->submenu);
  107. // Popup
  108. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewPopup);
  109. popup_free(uhf_app->popup);
  110. // Loading
  111. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewLoading);
  112. loading_free(uhf_app->loading);
  113. // TextInput
  114. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewTextInput);
  115. text_input_free(uhf_app->text_input);
  116. // Custom Widget
  117. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewWidget);
  118. widget_free(uhf_app->widget);
  119. // Worker
  120. uhf_worker_stop(uhf_app->worker);
  121. uhf_worker_free(uhf_app->worker);
  122. // View Dispatcher
  123. view_dispatcher_free(uhf_app->view_dispatcher);
  124. // Scene Manager
  125. scene_manager_free(uhf_app->scene_manager);
  126. // GUI
  127. furi_record_close(RECORD_GUI);
  128. uhf_app->gui = NULL;
  129. // Storage
  130. furi_record_close(RECORD_STORAGE);
  131. uhf_app->storage = NULL;
  132. // Notifications
  133. furi_record_close(RECORD_NOTIFICATION);
  134. uhf_app->notifications = NULL;
  135. free(uhf_app);
  136. }
  137. // void uhf_text_store_set(UHFApp* uhf_app, const char* text, ...) {
  138. // va_list args;
  139. // va_start(args, text);
  140. // vsnprintf(uhf_app->text_store, sizeof(uhf_app->text_store), text, args);
  141. // va_end(args);
  142. // }
  143. // void uhf_text_store_clear(UHFApp* uhf_app) {
  144. // memset(uhf_app->text_store, 0, sizeof(uhf_app->text_store));
  145. // }
  146. // ==================
  147. static const NotificationSequence uhf_sequence_blink_start_cyan = {
  148. &message_blink_start_10,
  149. &message_blink_set_color_cyan,
  150. &message_do_not_reset,
  151. NULL,
  152. };
  153. static const NotificationSequence uhf_sequence_blink_stop = {
  154. &message_blink_stop,
  155. NULL,
  156. };
  157. void uhf_blink_start(UHFApp* uhf_app) {
  158. notification_message(uhf_app->notifications, &uhf_sequence_blink_start_cyan);
  159. }
  160. void uhf_blink_stop(UHFApp* uhf_app) {
  161. notification_message(uhf_app->notifications, &uhf_sequence_blink_stop);
  162. }
  163. void uhf_show_loading_popup(void* ctx, bool show) {
  164. UHFApp* uhf_app = ctx;
  165. TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
  166. if(show) {
  167. // Raise timer priority so that animations can play
  168. vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
  169. view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewLoading);
  170. } else {
  171. // Restore default timer priority
  172. vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
  173. }
  174. }
  175. int32_t uhf_app_main(void* ctx) {
  176. UNUSED(ctx);
  177. UHFApp* uhf_app = uhf_alloc();
  178. scene_manager_next_scene(uhf_app->scene_manager, UHFSceneStart);
  179. view_dispatcher_run(uhf_app->view_dispatcher);
  180. uhf_free(uhf_app);
  181. return 0;
  182. }