nfc_apdu_runner_scene_running.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "../nfc_apdu_runner.h"
  2. #include "nfc_apdu_runner_scene.h"
  3. // NFC Worker回调函数
  4. static void nfc_worker_callback(NfcWorkerEvent event, void* context) {
  5. NfcApduRunner* app = context;
  6. // 发送自定义事件到视图分发器
  7. view_dispatcher_send_custom_event(app->view_dispatcher, event);
  8. }
  9. // 运行场景弹出窗口回调
  10. static void nfc_apdu_runner_scene_running_popup_callback(void* context) {
  11. NfcApduRunner* app = context;
  12. FURI_LOG_I("APDU_DEBUG", "弹出窗口回调");
  13. view_dispatcher_send_custom_event(app->view_dispatcher, NfcApduRunnerCustomEventPopupClosed);
  14. }
  15. // 显示错误消息并设置回调
  16. static void show_error_popup(NfcApduRunner* app, const char* message) {
  17. FURI_LOG_I("APDU_DEBUG", "显示错误弹窗: %s", message);
  18. Popup* popup = app->popup;
  19. popup_reset(popup);
  20. popup_set_text(popup, message, 64, 32, AlignCenter, AlignCenter);
  21. popup_set_timeout(popup, 2000);
  22. popup_set_callback(popup, nfc_apdu_runner_scene_running_popup_callback);
  23. popup_set_context(popup, app);
  24. view_dispatcher_switch_to_view(app->view_dispatcher, NfcApduRunnerViewPopup);
  25. }
  26. // 显示等待卡片弹出窗口
  27. static void show_waiting_popup(NfcApduRunner* app) {
  28. Popup* popup = app->popup;
  29. popup_reset(popup);
  30. popup_set_header(popup, "NFC APDU Runner", 64, 0, AlignCenter, AlignTop);
  31. popup_set_text(
  32. popup,
  33. "Waiting for card...\nPlace card on Flipper's back",
  34. 64,
  35. 32,
  36. AlignCenter,
  37. AlignCenter);
  38. popup_set_timeout(popup, 0);
  39. popup_set_context(popup, app);
  40. view_dispatcher_switch_to_view(app->view_dispatcher, NfcApduRunnerViewPopup);
  41. }
  42. // 显示运行中弹出窗口
  43. static void show_running_popup(NfcApduRunner* app) {
  44. Popup* popup = app->popup;
  45. popup_reset(popup);
  46. popup_set_header(popup, "Running APDU commands", 64, 0, AlignCenter, AlignTop);
  47. popup_set_text(
  48. popup, "Please wait...\nDo not remove the card", 64, 32, AlignCenter, AlignCenter);
  49. popup_set_timeout(popup, 0);
  50. popup_set_context(popup, app);
  51. view_dispatcher_switch_to_view(app->view_dispatcher, NfcApduRunnerViewPopup);
  52. }
  53. // 运行场景进入回调
  54. void nfc_apdu_runner_scene_running_on_enter(void* context) {
  55. NfcApduRunner* app = context;
  56. Popup* popup = app->popup;
  57. FURI_LOG_I("APDU_DEBUG", "进入运行场景");
  58. // 确保文件路径有效
  59. if(furi_string_empty(app->file_path)) {
  60. FURI_LOG_E("APDU_DEBUG", "文件路径为空");
  61. show_error_popup(app, "Invalid file path");
  62. return;
  63. }
  64. FURI_LOG_I("APDU_DEBUG", "文件路径: %s", furi_string_get_cstr(app->file_path));
  65. // 显示正在运行的弹出窗口
  66. FURI_LOG_I("APDU_DEBUG", "显示加载脚本弹窗");
  67. popup_reset(popup);
  68. popup_set_text(popup, "Loading script...\nPlease wait", 89, 44, AlignCenter, AlignCenter);
  69. popup_set_timeout(popup, 0);
  70. popup_set_context(popup, app);
  71. view_dispatcher_switch_to_view(app->view_dispatcher, NfcApduRunnerViewPopup);
  72. // 解析脚本文件
  73. FURI_LOG_I("APDU_DEBUG", "开始解析脚本文件");
  74. app->script = nfc_apdu_script_parse(app->storage, furi_string_get_cstr(app->file_path));
  75. if(app->script == NULL) {
  76. FURI_LOG_E("APDU_DEBUG", "解析脚本文件失败");
  77. show_error_popup(app, "Failed to parse script file");
  78. return;
  79. }
  80. FURI_LOG_I("APDU_DEBUG", "脚本解析成功, 卡类型: %d", app->script->card_type);
  81. // 检查卡类型是否支持
  82. if(app->script->card_type == CardTypeUnknown) {
  83. FURI_LOG_E("APDU_DEBUG", "不支持的卡类型");
  84. show_error_popup(app, "Unsupported card type");
  85. return;
  86. }
  87. FURI_LOG_I("APDU_DEBUG", "卡类型支持");
  88. // 显示等待卡片弹出窗口
  89. show_waiting_popup(app);
  90. // 重置卡片丢失标志
  91. app->card_lost = false;
  92. // 设置运行标志为true,允许执行APDU命令
  93. app->running = true;
  94. // 启动NFC Worker
  95. nfc_worker_start(app->worker, NfcWorkerStateRunning, app->script, nfc_worker_callback, app);
  96. }
  97. // 运行场景事件回调
  98. bool nfc_apdu_runner_scene_running_on_event(void* context, SceneManagerEvent event) {
  99. NfcApduRunner* app = context;
  100. bool consumed = false;
  101. if(event.type == SceneManagerEventTypeCustom) {
  102. // 处理自定义事件
  103. uint32_t custom_event = event.event;
  104. if(custom_event == NfcWorkerEventCardDetected) {
  105. FURI_LOG_I("APDU_DEBUG", "卡片检测成功事件");
  106. show_running_popup(app);
  107. consumed = true;
  108. } else if(custom_event == NfcWorkerEventSuccess) {
  109. FURI_LOG_I("APDU_DEBUG", "操作成功事件");
  110. // 获取响应结果
  111. nfc_worker_get_responses(app->worker, &app->responses, &app->response_count);
  112. // 切换到结果场景
  113. scene_manager_next_scene(app->scene_manager, NfcApduRunnerSceneResults);
  114. consumed = true;
  115. } else if(custom_event == NfcWorkerEventFail) {
  116. FURI_LOG_E("APDU_DEBUG", "操作失败事件");
  117. // 停止NFC Worker
  118. nfc_worker_stop(app->worker);
  119. // 获取自定义错误信息
  120. const char* error_message = nfc_worker_get_error_message(app->worker);
  121. if(error_message) {
  122. show_error_popup(app, error_message);
  123. } else {
  124. show_error_popup(
  125. app, "Failed to detect card or run APDU commands\nCheck the log for details");
  126. }
  127. consumed = true;
  128. } else if(custom_event == NfcWorkerEventCardLost) {
  129. FURI_LOG_E("APDU_DEBUG", "卡片丢失事件");
  130. // 不停止NFC Worker,而是显示等待卡片弹窗
  131. show_waiting_popup(app);
  132. consumed = true;
  133. } else if(custom_event == NfcWorkerEventAborted) {
  134. FURI_LOG_I("APDU_DEBUG", "操作被中止事件");
  135. // 停止NFC Worker
  136. nfc_worker_stop(app->worker);
  137. // 检查是否已经显示了错误信息
  138. const char* error_message = nfc_worker_get_error_message(app->worker);
  139. if(!error_message) {
  140. // 只有在没有错误信息的情况下才显示用户取消的消息
  141. show_error_popup(app, "Operation cancelled by user");
  142. }
  143. consumed = true;
  144. } else if(custom_event == NfcApduRunnerCustomEventPopupClosed) {
  145. FURI_LOG_I("APDU_DEBUG", "弹出窗口关闭事件");
  146. // 如果是错误弹窗关闭,返回到文件选择场景
  147. scene_manager_previous_scene(app->scene_manager);
  148. consumed = true;
  149. } else if(custom_event == NfcApduRunnerCustomEventViewExit) {
  150. FURI_LOG_I("APDU_DEBUG", "视图退出事件");
  151. // 用户请求退出,设置运行标志为false
  152. app->running = false;
  153. nfc_worker_stop(app->worker);
  154. consumed = true;
  155. }
  156. } else if(event.type == SceneManagerEventTypeBack) {
  157. FURI_LOG_I("APDU_DEBUG", "返回事件");
  158. // 用户按下返回键,设置运行标志为false并停止worker
  159. app->running = false;
  160. nfc_worker_stop(app->worker);
  161. consumed = false; // 不消费事件,让场景管理器处理返回
  162. }
  163. return consumed;
  164. }
  165. // 运行场景退出回调
  166. void nfc_apdu_runner_scene_running_on_exit(void* context) {
  167. NfcApduRunner* app = context;
  168. FURI_LOG_I("APDU_DEBUG", "退出运行场景");
  169. // 设置运行标志为false,停止任何正在进行的操作
  170. app->running = false;
  171. // 停止NFC Worker
  172. nfc_worker_stop(app->worker);
  173. // 释放脚本资源
  174. if(app->script) {
  175. nfc_apdu_script_free(app->script);
  176. app->script = NULL;
  177. }
  178. popup_reset(app->popup);
  179. }