| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- /*
- Wish list:
- 1. variable_item_set_current_value_text allows for large text, but
- it trucates it to X characters. It would be nice it it scrolled.
- */
- #include <furi.h>
- #include <furi_hal.h>
- #include <gui/gui.h>
- #include <gui/view.h>
- #include <gui/view_dispatcher.h>
- #include <gui/modules/submenu.h>
- #include <gui/modules/widget.h>
- #include <gui/modules/variable_item_list.h>
- #include <notification/notification.h>
- #include <notification/notification_messages.h>
- #include "rolling_flaws_icons.h"
- #include <lib/subghz/receiver.h>
- #include <lib/subghz/protocols/protocol_items.h>
- #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
- #include <lib/subghz/devices/devices.h>
- #include "rolling_flaws_subghz_receive.h"
- #include "rolling_flaws_settings.h"
- #include "rolling_flaws_about.h"
- #include "rolling_flaws_keeloq.h"
- #include "rolling_flaws_send_keeloq.h"
- #ifdef TAG
- #undef TAG
- #endif
- #define TAG "RollingFlawsSubGHzApp"
- // Comment this line if you don't want the backlight to be continuously on.
- #define BACKLIGHT_ALWAYS_ON yes
- typedef enum {
- RollingFlawsSubmenuIndexConfigure,
- RollingFlawsSubmenuIndexResetCountToZero,
- RollingFlawsSubmenuIndexTransmit,
- RollingFlawsSubmenuIndexReceive,
- RollingFlawsSubmenuIndexSyncRemote,
- RollingFlawsSubmenuIndexAbout,
- } RollingFlawsSubmenuIndex;
- typedef enum {
- RollingFlawsViewSubmenu,
- RollingFlawsViewConfigure,
- RollingFlawsViewReceiveSignals,
- RollingFlawsViewReceiveSync,
- RollingFlawsViewAbout,
- } RollingFlawsView;
- typedef enum {
- RollingFlawsEventIdReceivedSignal,
- RollingFlawsEventIdCycleSignal,
- } RollingFlawsEventId;
- static bool decode_packet(FuriString* buffer, void* ctx) {
- RollingFlaws* context = ctx;
- furi_hal_vibro_on(true);
- furi_delay_ms(50);
- furi_hal_vibro_on(false);
- if(furi_string_start_with_str(buffer, "KeeLoq 64bit")) {
- if(!furi_string_start_with_str(
- buffer, rolling_flaws_setting_protocol_base_name_get(context->model))) {
- FURI_LOG_I(TAG, "KeeLoq 64bit protocol is not enabled");
- return true;
- }
- decode_keeloq(context->model, buffer, false);
- } else {
- FURI_LOG_I(TAG, "Unknown protocol");
- }
- return true;
- }
- static bool sync_packet(FuriString* buffer, void* ctx) {
- RollingFlaws* context = ctx;
- if(furi_string_start_with_str(buffer, "KeeLoq 64bit")) {
- if(!furi_string_start_with_str(
- buffer, rolling_flaws_setting_protocol_base_name_get(context->model))) {
- FURI_LOG_I(TAG, "KeeLoq 64bit protocol is not enabled");
- return true;
- }
- decode_keeloq(context->model, buffer, true);
- view_dispatcher_send_custom_event(
- context->view_dispatcher, RollingFlawsEventIdReceivedSignal);
- return false;
- } else {
- FURI_LOG_I(TAG, "Unknown protocol");
- }
- return true;
- }
- /**
- * @brief Callback for navigation events
- * @details This function is called when user press back button. We return VIEW_NONE to
- * indicate that we want to exit the application.
- * @param context The context
- * @return next view id
- */
- uint32_t rolling_flaws_navigation_exit_callback(void* context) {
- UNUSED(context);
- return VIEW_NONE;
- }
- /**
- * @brief Callback for navigation events
- * @details This function is called when user press back button. We return VIEW_NONE to
- * indicate that we want to exit the application.
- * @param context The context
- * @return next view id
- */
- uint32_t rolling_flaws_navigation_submenu_callback(void* context) {
- UNUSED(context);
- return RollingFlawsViewSubmenu;
- }
- /**
- * @brief Callback for navigation events
- * @details This function is called when user press back button. We return VIEW_NONE to
- * indicate that we want to exit the application.
- * @param context The context
- * @return next view id
- */
- uint32_t rolling_flaws_navigation_submenu_stop_receiving_callback(void* context) {
- RollingFlaws* app = (RollingFlaws*)context;
- stop_listening(app->subghz);
- return RollingFlawsViewSubmenu;
- }
- uint32_t rolling_flaws_navigation_submenu_stop_sync_callback(void* context) {
- RollingFlaws* app = (RollingFlaws*)context;
- stop_listening(app->subghz);
- return RollingFlawsViewSubmenu;
- }
- bool rolling_flaws_view_dispatcher_custom_event_callback(void* context, uint32_t event) {
- FURI_LOG_I(TAG, "Custom event received: %ld", event);
- if(event == RollingFlawsEventIdReceivedSignal) {
- RollingFlaws* app = (RollingFlaws*)context;
- stop_listening(app->subghz);
- furi_hal_vibro_on(true);
- furi_delay_ms(200);
- furi_hal_vibro_on(false);
- furi_delay_ms(100);
- furi_hal_vibro_on(true);
- furi_delay_ms(100);
- furi_hal_vibro_on(false);
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewSubmenu);
- return true;
- }
- if(event == RollingFlawsEventIdCycleSignal) {
- RollingFlaws* app = (RollingFlaws*)context;
- stop_listening(app->subghz);
- uint32_t frequency = rolling_flaws_setting_frequency_get(app->model);
- app->model->opened = false;
- start_listening(app->subghz, frequency, decode_packet, app);
- }
- return false;
- }
- void rolling_flaws_submenu_callback(void* context, uint32_t index) {
- RollingFlaws* app = (RollingFlaws*)context;
- switch(index) {
- case RollingFlawsSubmenuIndexConfigure:
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewConfigure);
- break;
- case RollingFlawsSubmenuIndexResetCountToZero:
- app->model->count = 0x0;
- app->model->future_count = 0xFFFFFFFF;
- furi_hal_vibro_on(true);
- furi_delay_ms(200);
- furi_hal_vibro_on(false);
- break;
- case RollingFlawsSubmenuIndexTransmit:
- app->model->count++;
- app->model->future_count = 0xFFFFFFFF;
- send_keeloq_count(
- rolling_flaws_setting_fix_get(app->model),
- app->model->count - 2,
- rolling_flaws_setting_protocol_mf_name_get(app->model),
- rolling_flaws_setting_frequency_get(app->model));
- furi_hal_vibro_on(true);
- furi_delay_ms(100);
- furi_hal_vibro_on(false);
- furi_delay_ms(100);
- furi_hal_vibro_on(true);
- furi_delay_ms(200);
- furi_hal_vibro_on(false);
- break;
- case RollingFlawsSubmenuIndexReceive: {
- uint32_t frequency = rolling_flaws_setting_frequency_get(app->model);
- app->model->opened = false;
- start_listening(app->subghz, frequency, decode_packet, app);
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewReceiveSignals);
- } break;
- case RollingFlawsSubmenuIndexSyncRemote: {
- uint32_t frequency = rolling_flaws_setting_frequency_get(app->model);
- start_listening(app->subghz, frequency, sync_packet, app);
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewReceiveSync);
- } break;
- case RollingFlawsSubmenuIndexAbout:
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewAbout);
- break;
- default:
- break;
- }
- }
- void rolling_flaws_receive_sync_draw_callback(Canvas* canvas, void* model) {
- UNUSED(model);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 13, 30, "Syncing rolling code:");
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 13, 45, "Press remote button now.");
- }
- void rolling_flaws_receive_signal_draw_callback(Canvas* canvas, void* model) {
- RollingFlawsModel* my_model = ((RollingFlawsRefModel*)model)->model;
- FuriString* str = furi_string_alloc();
- canvas_set_bitmap_mode(canvas, 1);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 13, 8, "Rolling code receiver");
- canvas_set_font(canvas, FontSecondary);
- furi_string_printf(str, "Count: %04X", (uint16_t)my_model->count);
- canvas_draw_str(canvas, 2, 34, furi_string_get_cstr(str));
- canvas_set_font(canvas, FontSecondary);
- if(my_model->future_count > 0xFFFF) {
- canvas_draw_str(canvas, 2, 44, "Future: none");
- } else {
- furi_string_printf(str, "Future: %04X", (uint16_t)my_model->future_count);
- canvas_draw_str(canvas, 2, 44, furi_string_get_cstr(str));
- }
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 3, 20, rolling_flaws_setting_protocol_display_name_get(my_model));
- canvas_set_font(canvas, FontSecondary);
- furi_string_printf(str, "Fix: %08lX", rolling_flaws_setting_fix_get(my_model));
- canvas_draw_str(canvas, 2, 54, furi_string_get_cstr(str));
- canvas_set_font(canvas, FontSecondary);
- furi_string_printf(str, "RX: %s", furi_string_get_cstr(my_model->key));
- canvas_draw_str(canvas, 2, 64, furi_string_get_cstr(str));
- if(my_model->opened) {
- canvas_draw_icon(canvas, 100, 15, &I_Unlock_10x8);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 82, 33, "OPENED!");
- } else {
- canvas_draw_icon(canvas, 100, 15, &I_Lock_10x8);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 85, 33, "CLOSED");
- }
- canvas_set_font(canvas, FontSecondary);
- furi_string_printf(str, "%sMHz", rolling_flaws_setting_frequency_name_get(my_model));
- canvas_draw_str(canvas, 75, 43, furi_string_get_cstr(str));
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas, 82, 54, furi_string_get_cstr(my_model->status));
- furi_string_free(str);
- }
- bool rolling_flaws_view_input_ignore_callback(InputEvent* event, void* context) {
- UNUSED(event);
- UNUSED(context);
- return false;
- }
- bool rolling_flaws_view_input_callback(InputEvent* event, void* context) {
- RollingFlaws* app = (RollingFlaws*)context;
- RollingFlawsModel* my_model = app->model;
- FURI_LOG_I(TAG, "Input event received: %d", event->type);
- if(event->type == InputTypeShort) {
- FURI_LOG_I(TAG, "Input key: %d", event->key);
- if(event->key == InputKeyLeft) {
- if(my_model->count == 0) {
- my_model->count = 0xFFFF;
- } else {
- my_model->count--;
- }
- __gui_redraw();
- return true;
- }
- if(event->key == InputKeyRight) {
- if(my_model->count == 0xFFFF) {
- my_model->count = 0;
- } else {
- my_model->count++;
- }
- __gui_redraw();
- return true;
- }
- if(event->key == InputKeyOk) {
- my_model->opened = false;
- view_dispatcher_send_custom_event(
- app->view_dispatcher, RollingFlawsEventIdCycleSignal);
- __gui_redraw();
- return true;
- }
- }
- return false;
- }
- RollingFlaws* rolling_flaws_alloc() {
- RollingFlaws* app = (RollingFlaws*)malloc(sizeof(RollingFlaws));
- Gui* gui = furi_record_open(RECORD_GUI);
- app->subghz = rolling_flaws_subghz_alloc();
- app->model = malloc(sizeof(RollingFlawsModel));
- app->model->key = furi_string_alloc();
- app->model->custom_mf = furi_string_alloc();
- app->model->status = furi_string_alloc();
- app->model->custom_fix = 0x24321234;
- app->model->count = 0x0;
- app->model->future_count = 0xFFFFFFFF;
- app->model->opened = false;
- app->view_dispatcher = view_dispatcher_alloc();
- view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
- view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
- view_dispatcher_set_custom_event_callback(
- app->view_dispatcher, rolling_flaws_view_dispatcher_custom_event_callback);
- app->submenu = submenu_alloc();
- submenu_add_item(
- app->submenu,
- "Config",
- RollingFlawsSubmenuIndexConfigure,
- rolling_flaws_submenu_callback,
- app);
- submenu_add_item(
- app->submenu,
- "Reset count to 0",
- RollingFlawsSubmenuIndexResetCountToZero,
- rolling_flaws_submenu_callback,
- app);
- submenu_add_item(
- app->submenu,
- "Transmit Signal",
- RollingFlawsSubmenuIndexTransmit,
- rolling_flaws_submenu_callback,
- app);
- submenu_add_item(
- app->submenu,
- "Receive Signals",
- RollingFlawsSubmenuIndexReceive,
- rolling_flaws_submenu_callback,
- app);
- submenu_add_item(
- app->submenu,
- "Sync Remote",
- RollingFlawsSubmenuIndexSyncRemote,
- rolling_flaws_submenu_callback,
- app);
- submenu_add_item(
- app->submenu, "About", RollingFlawsSubmenuIndexAbout, rolling_flaws_submenu_callback, app);
- view_set_previous_callback(
- submenu_get_view(app->submenu), rolling_flaws_navigation_exit_callback);
- view_dispatcher_add_view(
- app->view_dispatcher, RollingFlawsViewSubmenu, submenu_get_view(app->submenu));
- view_dispatcher_switch_to_view(app->view_dispatcher, RollingFlawsViewSubmenu);
- rolling_flaw_populate_variable_item_list(app);
- view_set_previous_callback(
- variable_item_list_get_view(app->variable_item_list_config),
- rolling_flaws_navigation_submenu_callback);
- view_dispatcher_add_view(
- app->view_dispatcher,
- RollingFlawsViewConfigure,
- variable_item_list_get_view(app->variable_item_list_config));
- app->view_receive_signals = view_alloc();
- view_set_context(app->view_receive_signals, app);
- view_set_draw_callback(app->view_receive_signals, rolling_flaws_receive_signal_draw_callback);
- view_set_input_callback(app->view_receive_signals, rolling_flaws_view_input_callback);
- view_set_previous_callback(
- app->view_receive_signals, rolling_flaws_navigation_submenu_stop_receiving_callback);
- view_allocate_model(
- app->view_receive_signals, ViewModelTypeLockFree, sizeof(RollingFlawsRefModel));
- RollingFlawsRefModel* refmodel = view_get_model(app->view_receive_signals);
- refmodel->model = app->model;
- view_dispatcher_add_view(
- app->view_dispatcher, RollingFlawsViewReceiveSignals, app->view_receive_signals);
- app->view_receive_sync = view_alloc();
- view_set_context(app->view_receive_sync, app);
- view_set_draw_callback(app->view_receive_sync, rolling_flaws_receive_sync_draw_callback);
- view_set_input_callback(app->view_receive_sync, rolling_flaws_view_input_ignore_callback);
- view_set_previous_callback(
- app->view_receive_sync, rolling_flaws_navigation_submenu_stop_sync_callback);
- view_allocate_model(
- app->view_receive_sync, ViewModelTypeLockFree, sizeof(RollingFlawsRefModel));
- refmodel = view_get_model(app->view_receive_sync);
- refmodel->model = app->model;
- view_dispatcher_add_view(
- app->view_dispatcher, RollingFlawsViewReceiveSync, app->view_receive_sync);
- app->widget_about = widget_alloc();
- widget_add_text_scroll_element(app->widget_about, 0, 0, 128, 64, ROLLING_FLAWS_ABOUT_TEXT);
- view_set_previous_callback(
- widget_get_view(app->widget_about), rolling_flaws_navigation_submenu_callback);
- view_dispatcher_add_view(
- app->view_dispatcher, RollingFlawsViewAbout, widget_get_view(app->widget_about));
- app->notifications = furi_record_open(RECORD_NOTIFICATION);
- #ifdef BACKLIGHT_ALWAYS_ON
- notification_message(app->notifications, &sequence_display_backlight_enforce_on);
- #endif
- return app;
- }
- void rolling_flaws_free(RollingFlaws* app) {
- #ifdef BACKLIGHT_ALWAYS_ON
- notification_message(app->notifications, &sequence_display_backlight_enforce_auto);
- #endif
- furi_record_close(RECORD_NOTIFICATION);
- view_dispatcher_remove_view(app->view_dispatcher, RollingFlawsViewAbout);
- widget_free(app->widget_about);
- view_dispatcher_remove_view(app->view_dispatcher, RollingFlawsViewReceiveSignals);
- view_free(app->view_receive_signals);
- view_dispatcher_remove_view(app->view_dispatcher, RollingFlawsViewReceiveSync);
- view_free(app->view_receive_sync);
- view_dispatcher_remove_view(app->view_dispatcher, RollingFlawsViewConfigure);
- variable_item_list_free(app->variable_item_list_config);
- view_dispatcher_remove_view(app->view_dispatcher, RollingFlawsViewSubmenu);
- submenu_free(app->submenu);
- view_dispatcher_free(app->view_dispatcher);
- furi_record_close(RECORD_GUI);
- rolling_flaws_subghz_free(app->subghz);
- free(app);
- }
- int32_t rolling_flaws_app(void* p) {
- UNUSED(p);
- RollingFlaws* app = rolling_flaws_alloc();
- view_dispatcher_run(app->view_dispatcher);
- rolling_flaws_free(app);
- return 0;
- }
|