Преглед изворни кода

Merge pull request #5 from acegoal07/Early-Stop-2

Early stop 2
acegoal07 пре 2 година
родитељ
комит
940f7de4c0
7 измењених фајлова са 141 додато и 63 уклоњено
  1. 1 0
      .gitignore
  2. 2 10
      README.md
  3. 0 1
      build.txt
  4. 2 3
      lib/worker/nfc_playlist_worker.h
  5. 4 0
      nfc_playlist.h
  6. 119 48
      scences/emulation.c
  7. 13 1
      scences/emulation.h

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+notes.txt

+ 2 - 10
README.md

@@ -8,13 +8,5 @@ When you start the app there is a start button when pressed starts the playlist
 
 To set the playlist you need to create a file in ext/apps_data/nfc_playlist called playlist.txt you can find an example of the file in the repository
 
-## Know problems:
-- Unable to press any buttons while emulating as they are unresponsive and if you spam them it crashes the app (cause has been located and a fix is being made)
-- Emulating UI can be a bit janky not displaying as intended 100% of the time
-
-## TODO:
-- [x] Add basic UI
-- [X] Add checks for files that are not NFC and missing file and add a display for them
-- [X] Add the ability to adjust time between cards
-- [ ] Add the ability to adjust card queue from within the app
-- [ ] Make it so you can pause, stop and continue the running of the cards
+## How to build
+This app was design, built and tested using the <a href="https://github.com/Flipper-XFW/Xtreme-Firmware">Xtreme firmware</a> i don't see why it wont work with other firmwares but do keep this in mind when building it with FBT

+ 0 - 1
build.txt

@@ -1 +0,0 @@
-fbt fap_nfc_playlist && fbt launch APPSRC=applications_user/nfc_playlist

+ 2 - 3
lib/worker/nfc_playlist_worker.h

@@ -20,14 +20,13 @@ typedef struct NfcPlaylistWorker {
    Nfc* nfc;
 } NfcPlaylistWorker;
 
-/// Worker
 NfcPlaylistWorker* nfc_playlist_worker_alloc();
 void nfc_playlist_worker_free(NfcPlaylistWorker* nfc_playlist_worker);
 void nfc_playlist_worker_stop(NfcPlaylistWorker* nfc_playlist_worker);
 void nfc_playlist_worker_start(NfcPlaylistWorker* nfc_playlist_worker);
-// task
+
 int32_t nfc_playlist_worker_task(void* context);
-//
+
 bool nfc_playlist_worker_is_emulating(NfcPlaylistWorker* nfc_playlist_worker);
 void nfc_playlist_worker_set_nfc_data(NfcPlaylistWorker* nfc_playlist_worker, char* file_path);
 NfcDeviceData* nfc_playlist_worker_get_nfc_data(NfcPlaylistWorker* nfc_playlist_worker);

+ 4 - 0
nfc_playlist.h

@@ -1,5 +1,6 @@
 #pragma once
 #include <furi.h>
+#include <furi_hal.h>
 #include <string.h>
 #include <gui/gui.h>
 #include <gui/view_dispatcher.h>
@@ -7,6 +8,7 @@
 #include <gui/modules/popup.h>
 #include <gui/modules/variable_item_list.h>
 #include <notification/notification_messages.h>
+#include <nfc_playlist_worker.h>
 
 typedef enum {
    NfcPlaylistView_Menu,
@@ -25,6 +27,8 @@ typedef struct {
    VariableItemList* variable_item_list;
    Popup* popup;
    NotificationApp* notification;
+   FuriThread* thread;
+   NfcPlaylistWorker* nfc_playlist_worker;
    uint8_t emulate_timeout;
    uint8_t emulate_delay;
    bool emulate_led_indicator;

+ 119 - 48
scences/emulation.c

@@ -1,99 +1,170 @@
 #include "nfc_playlist.h"
 #include "scences/emulation.h"
 
+NfcPlaylistEmulationState EmulationState = NfcPlaylistEmulationState_Stopped;
+
 void nfc_playlist_emulation_scene_on_enter(void* context) {
     NfcPlaylist* nfc_playlist = context;
+    nfc_playlist_emulation_setup(nfc_playlist);
+    nfc_playlist_emulation_start(nfc_playlist);
+}
+
+bool nfc_playlist_emulation_scene_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    FURI_LOG_RAW_I("nfc_playlist_emulation_scene_on_event: %ld", event.event);
+    switch (event.event) {
+        case 0:
+            if (EmulationState == NfcPlaylistEmulationState_Emulating) {
+                EmulationState = NfcPlaylistEmulationState_Canceled;
+                return true;
+            }
+        default:
+            break;
+    }
+
+    return false;
+}
+
+void nfc_playlist_emulation_scene_on_exit(void* context) {
+    NfcPlaylist* nfc_playlist = context;
+    EmulationState = NfcPlaylistEmulationState_Stopped;
+    nfc_playlist_emulation_stop(nfc_playlist);
+    nfc_playlist_emulation_free(nfc_playlist);
+    popup_reset(nfc_playlist->popup);
+}
 
+void nfc_playlist_emulation_setup(void* context) {
+    NfcPlaylist* nfc_playlist = context;
+
+    nfc_playlist->thread = furi_thread_alloc_ex(
+        "NfcPlaylistEmulationWorker", 8192, nfc_playlist_emulation_task, nfc_playlist);
+    nfc_playlist->nfc_playlist_worker = nfc_playlist_worker_alloc();
+}
+
+void nfc_playlist_emulation_free(NfcPlaylist* nfc_playlist) {
+    furi_assert(nfc_playlist);
+    furi_thread_free(nfc_playlist->thread);
+    nfc_playlist_worker_free(nfc_playlist->nfc_playlist_worker);
+    nfc_playlist->thread = NULL;
+    nfc_playlist->nfc_playlist_worker = NULL;
+}
+
+void nfc_playlist_emulation_start(NfcPlaylist* nfc_playlist) {
+    furi_assert(nfc_playlist);
+    furi_thread_start(nfc_playlist->thread);
+}
+
+void nfc_playlist_emulation_stop(NfcPlaylist* nfc_playlist) {
+    furi_assert(nfc_playlist);
+    furi_thread_join(nfc_playlist->thread);
+}
+
+int32_t nfc_playlist_emulation_task(void* context) {
+    NfcPlaylist* nfc_playlist = context;
     // open/alloc resources
     Storage* storage = furi_record_open(RECORD_STORAGE);
     Stream* stream = file_stream_alloc(storage);
     FuriString* line = furi_string_alloc();
-    NfcPlaylistWorker* nfc_worker = nfc_playlist_worker_alloc();
+
+    popup_reset(nfc_playlist->popup);
+    popup_set_context(nfc_playlist->popup, nfc_playlist);
+    view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup);
+
     // Read file
     if(file_stream_open(stream, APP_DATA_PATH("playlist.txt"), FSAM_READ, FSOM_OPEN_EXISTING)) {
-        popup_reset(nfc_playlist->popup);
-        popup_set_context(nfc_playlist->popup, nfc_playlist);
-        popup_set_header(nfc_playlist->popup, "Emulating:", 64, 10, AlignCenter, AlignTop);
-        view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup);
-
+        EmulationState = NfcPlaylistEmulationState_Emulating;
         int file_position = 0;
         // read the file line by line and print the text
-        while(stream_read_line(stream, line)) {
+        while(stream_read_line(stream, line) && EmulationState == NfcPlaylistEmulationState_Emulating) {
             if (options_emulate_delay[nfc_playlist->emulate_delay] > 0) {
                 if (file_position > 0) {
+                    popup_set_header(nfc_playlist->popup, "Delaying", 64, 10, AlignCenter, AlignTop);
                     start_error_blink(nfc_playlist);
                     int time_counter_delay_ms = (options_emulate_delay[nfc_playlist->emulate_delay] * 1000);
                     do {
-                        char display_text[30];
-                        snprintf(display_text, 30, "%s\n\n%ds", "Delaying...", (time_counter_delay_ms/1000));
-                        popup_set_text(nfc_playlist->popup, display_text, 64, 25, AlignCenter, AlignTop);
+                        char display_text[10];
+                        snprintf(display_text, 10, "%ds", (time_counter_delay_ms/1000));
+                        popup_set_text(nfc_playlist->popup, display_text, 64, 50, AlignCenter, AlignTop);
                         furi_delay_ms(500);
                         time_counter_delay_ms -= 500;
-                    } while(time_counter_delay_ms > 0);
+                    } while(time_counter_delay_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating);
                 } else {
                     file_position++;
                 }
             }
 
+            if (EmulationState != NfcPlaylistEmulationState_Emulating) {
+                break;
+            }
+
             char* file_path = (char*)furi_string_get_cstr(line);
-            char* file_name = &strrchr(file_path, '/')[1];
+            char* file_name;
+            if (strchr(file_path, '/') != NULL) {
+                file_name = &strrchr(file_path, '/')[1];
+            } else {
+                file_name = file_path;
+            }
+            char* file_ext = &strrchr(file_path, '.')[1];
             int time_counter_ms = (options_emulate_timeout[nfc_playlist->emulate_timeout] * 1000);
 
             if (storage_file_exists(storage, file_path) == false) {
+                char popup_header_text[80];
+                snprintf(popup_header_text, 80, "%s\n%s", "ERROR not found:", file_name);
+                popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
                 start_error_blink(nfc_playlist);
-                char const* popup_text_unformatted = strcat(file_name, "\nnot found");
-                int popup_text_size = (strlen(popup_text_unformatted) + 4);
-                char popup_text[popup_text_size];
-
-                do {
-                    snprintf(popup_text, popup_text_size, "%s\n%ds", file_name, (time_counter_ms/1000));
-                    popup_set_text(nfc_playlist->popup, popup_text, 64, 25, AlignCenter, AlignTop);
+                while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
+                    char popup_text[10];
+                    snprintf(popup_text, 10, "%ds", (time_counter_ms/1000));
+                    popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
                     furi_delay_ms(500);
                     time_counter_ms -= 500;
-                } while(time_counter_ms > 0);
-            } else {
-                start_normal_blink(nfc_playlist);
-                nfc_playlist_worker_set_nfc_data(nfc_worker, file_path);
-                nfc_playlist_worker_start(nfc_worker);
+                }
+            }
 
-                int popup_text_size = (strlen(file_name) + 4);
-                char popup_text[popup_text_size];
+            else if (strcasestr(file_ext, "nfc") == NULL) {
+                char popup_header_text[80];
+                snprintf(popup_header_text, 80, "%s\n%s", "ERROR invalid file:", file_name);
+                popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
+                start_error_blink(nfc_playlist);
+                while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
+                    char popup_text[10];
+                    snprintf(popup_text, 10, "%ds", (time_counter_ms/1000));
+                    popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
+                    furi_delay_ms(500);
+                    time_counter_ms -= 500;
+                }
+            }
 
-                do {
-                    snprintf(popup_text, popup_text_size, "%s\n%ds", file_name, (time_counter_ms/1000));
-                    popup_set_text(nfc_playlist->popup, popup_text, 64, 25, AlignCenter, AlignTop);
+            else {
+                char popup_header_text[80];
+                snprintf(popup_header_text, 80, "%s\n%s", "Emulating:", file_name);
+                popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
+                nfc_playlist_worker_set_nfc_data(nfc_playlist->nfc_playlist_worker, file_path);
+                nfc_playlist_worker_start(nfc_playlist->nfc_playlist_worker);
+                start_normal_blink(nfc_playlist);
+                while(nfc_playlist_worker_is_emulating(nfc_playlist->nfc_playlist_worker) && time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
+                    char popup_text[10];
+                    snprintf(popup_text, 10, "%ds", (time_counter_ms/1000));
+                    popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
                     furi_delay_ms(500);
                     time_counter_ms -= 500;
-                } while(nfc_playlist_worker_is_emulating(nfc_worker) && time_counter_ms > 0);
-                nfc_playlist_worker_stop(nfc_worker);
+                }
+                nfc_playlist_worker_stop(nfc_playlist->nfc_playlist_worker);
             }
         }
+        EmulationState = NfcPlaylistEmulationState_Stopped;
         popup_reset(nfc_playlist->popup);
-        scene_manager_previous_scene(nfc_playlist->scene_manager);
+        popup_set_header(nfc_playlist->popup, "Emulation finished", 64, 10, AlignCenter, AlignTop);
+        popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop);
         stop_blink(nfc_playlist);
     } else {
-        popup_reset(nfc_playlist->popup);
-        popup_set_context(nfc_playlist->popup, nfc_playlist);
         popup_set_header(nfc_playlist->popup, "Error:", 64, 10, AlignCenter, AlignTop);
         popup_set_text(nfc_playlist->popup, "Failed to open file\n/ext/apps_data/nfc_playlist/playlist.txt", 64, 25, AlignCenter, AlignTop);
-        view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup);
     }
     // Free/close resources
     furi_string_free(line);
     file_stream_close(stream);
     stream_free(stream);
-    nfc_playlist_worker_free(nfc_worker);
     // Close storage
-    furi_record_close(RECORD_STORAGE);
-}
-
-bool nfc_playlist_emulation_scene_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
-    UNUSED(event);
-    return false;
-}
-
-void nfc_playlist_emulation_scene_on_exit(void* context) {
-   NfcPlaylist* nfc_playlist = context;
-   popup_reset(nfc_playlist->popup);
+    return 0;
 }

+ 13 - 1
scences/emulation.h

@@ -12,4 +12,16 @@
 
 void nfc_playlist_emulation_scene_on_enter(void* context);
 bool nfc_playlist_emulation_scene_on_event(void* context, SceneManagerEvent event);
-void nfc_playlist_emulation_scene_on_exit(void* context);
+void nfc_playlist_emulation_scene_on_exit(void* context);
+
+void nfc_playlist_emulation_setup(void* context);
+void nfc_playlist_emulation_free(NfcPlaylist* nfc_playlist);
+void nfc_playlist_emulation_start(NfcPlaylist* nfc_playlist);
+void nfc_playlist_emulation_stop(NfcPlaylist* nfc_playlist);
+int32_t nfc_playlist_emulation_task(void* context);
+
+typedef enum NfcPlaylistEmulationState {
+   NfcPlaylistEmulationState_Emulating,
+   NfcPlaylistEmulationState_Stopped,
+   NfcPlaylistEmulationState_Canceled,
+} NfcPlaylistEmulationState;