Skip to content

Commit b066300

Browse files
committed
1 parent 94e5cbb commit b066300

25 files changed

+1087
-0
lines changed
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
notes.txt
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# FlipperZero_NFC_Playlist:
2+
The idea behind this app is to allow for you to test multiple copies of NFC's at once as a bulk test
3+
4+
## How it works:
5+
When starting the app you are greeted by a select file option where you choose the playlist you wanna run.
6+
7+
All the playlists should be placed in ext/apps_data/nfc_playlist and an example of how the data in the file should look can be found below.
8+
```txt
9+
/ext/nfc/link.nfc
10+
/ext/nfc/link2.nfc
11+
```
12+
An example file can be found in the repository
13+
14+
## How to build
15+
This app was design, built and tested using the <a href="https://github.com/Flipper-XFW/Xtreme-Firmware">Xtreme firmware</a> so keep that in mind when building the FAP for yourself
16+
17+
## Settings:
18+
- Emulate time (How long the NFC card will be emulated for)
19+
- Delay time (How long the gap between the cards will be)
20+
- LED indicator (Whether or not the LED's will be on)
21+
- Reset settings (Puts all the settings back to the defaults)
22+
23+
## Playlist editor:
24+
- Delete playlist (Deletes the selected playlist)
25+
- Rename playlist (Renames the selected playlist the new name provided)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
App(
2+
appid="nfc_playlist",
3+
name="NFC Playlist",
4+
apptype=FlipperAppType.EXTERNAL,
5+
entry_point="nfc_playlist_main",
6+
requires=["gui", "nfc"],
7+
stack_size=4 * 1024,
8+
fap_category="NFC",
9+
fap_author="@acegoal07",
10+
fap_weburl="https://github.com/acegoal07/FlipperZero_NFC_Playlist/tree/main",
11+
fap_version="1.4",
12+
fap_icon="icon.png",
13+
fap_icon_assets="assets",
14+
fap_private_libs=[
15+
Lib(
16+
name="worker",
17+
),
18+
Lib(
19+
name="led",
20+
),
21+
],
22+
)
299 Bytes
Loading
304 Bytes
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "nfc_playlist_led.h"
2+
3+
NotificationMessage blink_message_normal = {
4+
.type = NotificationMessageTypeLedBlinkStart,
5+
.data.led_blink.color = LightBlue | LightGreen,
6+
.data.led_blink.on_time = 10,
7+
.data.led_blink.period = 100
8+
};
9+
const NotificationSequence blink_sequence_normal = {
10+
&blink_message_normal,
11+
&message_do_not_reset,
12+
NULL
13+
};
14+
15+
NotificationMessage blink_message_error = {
16+
.type = NotificationMessageTypeLedBlinkStart,
17+
.data.led_blink.color = LightRed,
18+
.data.led_blink.on_time = 10,
19+
.data.led_blink.period = 100
20+
};
21+
22+
const NotificationSequence blink_sequence_error = {
23+
&blink_message_error,
24+
&message_do_not_reset,
25+
NULL
26+
};
27+
28+
void start_blink(NfcPlaylist* nfc_playlist, int state) {
29+
if (nfc_playlist->settings.emulate_led_indicator) {
30+
if (state == NfcPlaylistLedState_Normal) {
31+
notification_message_block(nfc_playlist->notification, &blink_sequence_normal);
32+
} else if (state == NfcPlaylistLedState_Error) {
33+
notification_message_block(nfc_playlist->notification, &blink_sequence_error);
34+
}
35+
}
36+
}
37+
38+
void stop_blink(NfcPlaylist* nfc_playlist) {
39+
if (nfc_playlist->settings.emulate_led_indicator) {
40+
notification_message_block(nfc_playlist->notification, &sequence_blink_stop);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include <../../nfc_playlist.h>
3+
#include <notification/notification_messages.h>
4+
5+
typedef enum NfcPlaylistLedState {
6+
NfcPlaylistLedState_Normal,
7+
NfcPlaylistLedState_Error
8+
} NfcPlaylistLedState;
9+
10+
void start_blink(NfcPlaylist* nfc_playlist, int state);
11+
void stop_blink(NfcPlaylist* nfc_playlist);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include "nfc_playlist_worker.h"
2+
3+
NfcPlaylistWorker* nfc_playlist_worker_alloc() {
4+
NfcPlaylistWorker* nfc_playlist_worker = malloc(sizeof(NfcPlaylistWorker));
5+
6+
nfc_playlist_worker->thread = furi_thread_alloc_ex("NfcPlaylistWorker", 8192, nfc_playlist_worker_task, nfc_playlist_worker);
7+
nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped;
8+
9+
nfc_playlist_worker->nfc = nfc_alloc();
10+
nfc_playlist_worker->nfc_device = nfc_device_alloc();
11+
12+
return nfc_playlist_worker;
13+
}
14+
15+
void nfc_playlist_worker_free(NfcPlaylistWorker* nfc_playlist_worker) {
16+
furi_assert(nfc_playlist_worker);
17+
furi_thread_free(nfc_playlist_worker->thread);
18+
19+
nfc_free(nfc_playlist_worker->nfc);
20+
nfc_device_free(nfc_playlist_worker->nfc_device);
21+
22+
free(nfc_playlist_worker);
23+
}
24+
25+
void nfc_playlist_worker_stop(NfcPlaylistWorker* nfc_playlist_worker) {
26+
furi_assert(nfc_playlist_worker);
27+
if (nfc_playlist_worker->state != NfcPlaylistWorkerState_Stopped) {
28+
nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped;
29+
furi_thread_join(nfc_playlist_worker->thread);
30+
}
31+
}
32+
33+
void nfc_playlist_worker_start(NfcPlaylistWorker* nfc_playlist_worker) {
34+
furi_assert(nfc_playlist_worker);
35+
nfc_playlist_worker->state = NfcPlaylistWorkerState_Emulating;
36+
furi_thread_start(nfc_playlist_worker->thread);
37+
}
38+
39+
int32_t nfc_playlist_worker_task(void* context) {
40+
NfcPlaylistWorker* nfc_playlist_worker = context;
41+
42+
if (nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating) {
43+
44+
nfc_playlist_worker->nfc_listener =
45+
nfc_listener_alloc(nfc_playlist_worker->nfc,
46+
nfc_playlist_worker->nfc_protocol,
47+
nfc_device_get_data(nfc_playlist_worker->nfc_device, nfc_playlist_worker->nfc_protocol)
48+
);
49+
nfc_listener_start(nfc_playlist_worker->nfc_listener, NULL, NULL);
50+
51+
while(nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating) {
52+
furi_delay_ms(50);
53+
}
54+
55+
nfc_listener_stop(nfc_playlist_worker->nfc_listener);
56+
nfc_listener_free(nfc_playlist_worker->nfc_listener);
57+
}
58+
59+
nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped;
60+
61+
return 0;
62+
}
63+
64+
bool nfc_playlist_worker_is_emulating(NfcPlaylistWorker* nfc_playlist_worker) {
65+
if (nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating) {
66+
return true;
67+
}
68+
return false;
69+
}
70+
71+
void nfc_playlist_worker_set_nfc_data(NfcPlaylistWorker* nfc_playlist_worker, char* file_path) {
72+
nfc_device_clear(nfc_playlist_worker->nfc_device);
73+
nfc_device_load(nfc_playlist_worker->nfc_device, file_path);
74+
nfc_playlist_worker->nfc_protocol = nfc_device_get_protocol(nfc_playlist_worker->nfc_device);
75+
}
76+
77+
void nfc_playlist_worker_clear_nfc_data(NfcPlaylistWorker* nfc_playlist_worker) {
78+
nfc_device_clear(nfc_playlist_worker->nfc_device);
79+
}
80+
81+
NfcDeviceData* nfc_playlist_worker_get_nfc_data(NfcPlaylistWorker* nfc_playlist_worker) {
82+
return nfc_playlist_worker->nfc_data;
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
#include <furi.h>
3+
#include <furi_hal.h>
4+
#include <nfc/nfc.h>
5+
#include <nfc/nfc_device.h>
6+
#include <nfc/nfc_listener.h>
7+
8+
typedef enum NfcPlaylistWorkerState {
9+
NfcPlaylistWorkerState_Emulating,
10+
NfcPlaylistWorkerState_Stopped
11+
} NfcPlaylistWorkerState;
12+
13+
typedef struct NfcPlaylistWorker {
14+
FuriThread* thread;
15+
NfcPlaylistWorkerState state;
16+
NfcListener* nfc_listener;
17+
NfcDevice* nfc_device;
18+
NfcProtocol nfc_protocol;
19+
NfcDeviceData* nfc_data;
20+
Nfc* nfc;
21+
} NfcPlaylistWorker;
22+
23+
NfcPlaylistWorker* nfc_playlist_worker_alloc();
24+
void nfc_playlist_worker_free(NfcPlaylistWorker* nfc_playlist_worker);
25+
void nfc_playlist_worker_stop(NfcPlaylistWorker* nfc_playlist_worker);
26+
void nfc_playlist_worker_start(NfcPlaylistWorker* nfc_playlist_worker);
27+
28+
int32_t nfc_playlist_worker_task(void* context);
29+
30+
bool nfc_playlist_worker_is_emulating(NfcPlaylistWorker* nfc_playlist_worker);
31+
void nfc_playlist_worker_set_nfc_data(NfcPlaylistWorker* nfc_playlist_worker, char* file_path);
32+
void nfc_playlist_worker_clear_nfc_data(NfcPlaylistWorker* nfc_playlist_worker);
33+
NfcDeviceData* nfc_playlist_worker_get_nfc_data(NfcPlaylistWorker* nfc_playlist_worker);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#include "nfc_playlist.h"
2+
#include "nfc_playlist_i.h"
3+
4+
static void (*const nfc_playlist_scene_on_enter_handlers[])(void*) = {
5+
nfc_playlist_main_menu_scene_on_enter,
6+
nfc_playlist_settings_scene_on_enter,
7+
nfc_playlist_emulation_scene_on_enter,
8+
nfc_playlist_file_select_scene_on_enter,
9+
nfc_playlist_file_edit_scene_on_enter,
10+
nfc_playlist_text_input_scene_on_enter
11+
};
12+
13+
static bool (*const nfc_playlist_scene_on_event_handlers[])(void*, SceneManagerEvent) = {
14+
nfc_playlist_main_menu_scene_on_event,
15+
nfc_playlist_settings_scene_on_event,
16+
nfc_playlist_emulation_scene_on_event,
17+
nfc_playlist_file_select_scene_on_event,
18+
nfc_playlist_file_edit_scene_on_event,
19+
nfc_playlist_text_input_scene_on_event
20+
};
21+
22+
static void (*const nfc_playlist_scene_on_exit_handlers[])(void*) = {
23+
nfc_playlist_main_menu_scene_on_exit,
24+
nfc_playlist_settings_scene_on_exit,
25+
nfc_playlist_emulation_scene_on_exit,
26+
nfc_playlist_file_select_scene_on_exit,
27+
nfc_playlist_file_edit_scene_on_exit,
28+
nfc_playlist_text_input_scene_on_exit
29+
};
30+
31+
static const SceneManagerHandlers nfc_playlist_scene_manager_handlers = {
32+
.on_enter_handlers = nfc_playlist_scene_on_enter_handlers,
33+
.on_event_handlers = nfc_playlist_scene_on_event_handlers,
34+
.on_exit_handlers = nfc_playlist_scene_on_exit_handlers,
35+
.scene_num = NfcPlaylistScene_count
36+
};
37+
38+
static bool nfc_playlist_custom_callback(void* context, uint32_t custom_event) {
39+
furi_assert(context);
40+
NfcPlaylist* nfc_playlist = context;
41+
return scene_manager_handle_custom_event(nfc_playlist->scene_manager, custom_event);
42+
}
43+
44+
static bool nfc_playlist_back_event_callback(void* context) {
45+
furi_assert(context);
46+
NfcPlaylist* nfc_playlist = context;
47+
return scene_manager_handle_back_event(nfc_playlist->scene_manager);
48+
}
49+
50+
static NfcPlaylist* nfc_playlist_alloc() {
51+
NfcPlaylist* nfc_playlist = malloc(sizeof(NfcPlaylist));
52+
furi_assert(nfc_playlist);
53+
nfc_playlist->scene_manager = scene_manager_alloc(&nfc_playlist_scene_manager_handlers, nfc_playlist);
54+
nfc_playlist->view_dispatcher = view_dispatcher_alloc();
55+
view_dispatcher_enable_queue(nfc_playlist->view_dispatcher);
56+
nfc_playlist->variable_item_list = variable_item_list_alloc();
57+
nfc_playlist->submenu = submenu_alloc();
58+
59+
nfc_playlist->settings.base_file_path = furi_string_alloc_set_str("/ext/apps_data/nfc_playlist/");
60+
nfc_playlist->settings.file_path = nfc_playlist->settings.base_file_path;
61+
nfc_playlist->settings.file_selected = false;
62+
nfc_playlist->settings.file_selected_check = false;
63+
nfc_playlist->settings.emulate_timeout = default_emulate_timeout;
64+
nfc_playlist->settings.emulate_delay = default_emulate_delay;
65+
nfc_playlist->settings.emulate_led_indicator = default_emulate_led_indicator;
66+
67+
nfc_playlist->notification = furi_record_open(RECORD_NOTIFICATION);
68+
nfc_playlist->file_browser = file_browser_alloc(nfc_playlist->settings.file_path);
69+
nfc_playlist->text_input = text_input_alloc();
70+
nfc_playlist->popup = popup_alloc();
71+
72+
view_dispatcher_set_event_callback_context(nfc_playlist->view_dispatcher, nfc_playlist);
73+
view_dispatcher_set_custom_event_callback(nfc_playlist->view_dispatcher, nfc_playlist_custom_callback);
74+
view_dispatcher_set_navigation_event_callback(nfc_playlist->view_dispatcher, nfc_playlist_back_event_callback);
75+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Menu, submenu_get_view(nfc_playlist->submenu));
76+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Settings, variable_item_list_get_view(nfc_playlist->variable_item_list));
77+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup, popup_get_view(nfc_playlist->popup));
78+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileSelect, file_browser_get_view(nfc_playlist->file_browser));
79+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileEdit, submenu_get_view(nfc_playlist->submenu));
80+
view_dispatcher_add_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput, text_input_get_view(nfc_playlist->text_input));
81+
return nfc_playlist;
82+
}
83+
84+
static void nfc_playlist_free(NfcPlaylist* nfc_playlist) {
85+
furi_assert(nfc_playlist);
86+
scene_manager_free(nfc_playlist->scene_manager);
87+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Menu);
88+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Settings);
89+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup);
90+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileSelect);
91+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileEdit);
92+
view_dispatcher_remove_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput);
93+
view_dispatcher_free(nfc_playlist->view_dispatcher);
94+
variable_item_list_free(nfc_playlist->variable_item_list);
95+
submenu_free(nfc_playlist->submenu);
96+
file_browser_free(nfc_playlist->file_browser);
97+
text_input_free(nfc_playlist->text_input);
98+
popup_free(nfc_playlist->popup);
99+
furi_record_close(RECORD_NOTIFICATION);
100+
furi_string_free(nfc_playlist->settings.base_file_path);
101+
furi_string_free(nfc_playlist->settings.file_path);
102+
free(nfc_playlist->playlist_name);
103+
free(nfc_playlist);
104+
}
105+
106+
int32_t nfc_playlist_main(void* p) {
107+
UNUSED(p);
108+
109+
NfcPlaylist* nfc_playlist = nfc_playlist_alloc();
110+
111+
Gui* gui = furi_record_open(RECORD_GUI);
112+
view_dispatcher_attach_to_gui(nfc_playlist->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
113+
scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu);
114+
view_dispatcher_run(nfc_playlist->view_dispatcher);
115+
116+
furi_record_close(RECORD_GUI);
117+
nfc_playlist_free(nfc_playlist);
118+
119+
return 0;
120+
}

0 commit comments

Comments
 (0)