diff --git a/ReadMe.md b/ReadMe.md index eb44ddeaf..d0a4d1551 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -18,6 +18,8 @@ - Unleashed PR [Flappy: Border hitboxes, bigger Pilars #114 (By TQMatvey)](https://github.com/DarkFlippers/unleashed-firmware/pull/114) - Updated: [BlackJack (By teeebor)](https://github.com/teeebor/flipper_games) - Updated: [DTMF Dolphin (By litui)](https://github.com/litui/dtmf_dolphin) +- Added: [SAM (By Unknown)][Original?](https://github.com/ctoth/SAM) +- Added: [IFTTT Virtual Button (By Ferrazzi)](https://github.com/Ferrazzi/FlipperZero_IFTTT_Virtual_Button) `Req: ESP8266 w/ IFTTT FW Flashed`
TO DO / REMOVED
@@ -211,6 +213,7 @@ $ ./fbt plugin_dist - [Dolphin Backup (By nminaylov)](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) Modified by RogueMaster - [Dolphin Restorer (By nminaylov)](https://github.com/flipperdevices/flipperzero-firmware/pull/1384) Cloned by RogueMaster - [DTMF Dolphin (By litui)](https://github.com/litui/dtmf_dolphin) +- [IFTTT Virtual Button (By Ferrazzi)](https://github.com/Ferrazzi/FlipperZero_IFTTT_Virtual_Button) `Req: ESP8266 w/ IFTTT FW Flashed` - [Metronome (By panki27)](https://github.com/panki27/Metronome) - [Mouse Jacker (By mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/mousejacker) from nocomp/Frog/UberGuidoZ) `Req: NRF24` - [Mouse Jiggler (By Jacob-Tate)](https://github.com/Jacob-Tate/flipperzero-firmware/blob/dev/applications/mouse_jiggler/mouse_jiggler.c) (Original By MuddleBox) @@ -223,6 +226,7 @@ $ ./fbt plugin_dist - [Pomodoro Timer (By sbrin)](https://github.com/sbrin/flipperzero_pomodoro) - [RFID Fuzzer (By Ganapati)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/245) [Changes by Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware) - [RF Remix (By ESurge)](https://github.com/ESurge/flipperzero-firmware-unirfremix) [(Original By jimilinuxguy)](https://github.com/jimilinuxguy/flipperzero-universal-rf-remote/tree/028d615c83f059bb2c905530ddb3d4efbd3cbcae/applications/jukebox) [(More protocols thanks to darmiel & xMasterX)](https://github.com/darmiel/flipper-playlist/blob/feat/unirf-protocols/applications/unirfremix/unirfremix_app.c) +- [SAM (By Unknown)][Original?](https://github.com/ctoth/SAM) - [Sentry Safe (By H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/sentry_safe) from [UberGuidoZ](https://github.com/UberGuidoZ/)) - [Spectrum Analyzer (By jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) [Updates (for testing) Thanks to theY4Kman](https://github.com/theY4Kman/flipperzero-firmware) - [Sub-GHz Bruteforcer (By Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57) @@ -234,7 +238,7 @@ $ ./fbt plugin_dist - [USB Keyboard (By huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard) - [WAV Player (By Zlo)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) Updated by Atmanos & RogueMaster To Work - [WiFi (Deauther) (By Timmotools)](https://github.com/Timmotools/flipperzero_esp8266_deautherv2) -- [WiFi (Marauder) (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `REQUIRES ESP32 WITH MARAUDER FLASHED` +- [WiFi (Marauder) (By 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) `Req: ESP32 WITH MARAUDER FLASHED` - [WiFi Scanner v.0.4 (By SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module-ESP8266) `Req: ESP8266 or ESP32`
diff --git a/applications/plugins/ifttt/application.fam b/applications/plugins/ifttt/application.fam new file mode 100644 index 000000000..495627429 --- /dev/null +++ b/applications/plugins/ifttt/application.fam @@ -0,0 +1,14 @@ +App( + appid="ESP8266_IFTTT_Virtual_Button", + name="[ESP8266] IFTTT Virtual Button", + apptype=FlipperAppType.EXTERNAL, + entry_point="ifttt_virtual_button_app", + cdefines=["APP_IFTTT_VIRTUAL_BUTTON"], + requires=[ + "gui", + ], + stack_size=2 * 1024, + order=20, + fap_icon="icon.png", + fap_category="GPIO", +) \ No newline at end of file diff --git a/applications/plugins/ifttt/icon.png b/applications/plugins/ifttt/icon.png new file mode 100644 index 000000000..f6d586b38 Binary files /dev/null and b/applications/plugins/ifttt/icon.png differ diff --git a/applications/plugins/ifttt/ifttt_virtual_button.c b/applications/plugins/ifttt/ifttt_virtual_button.c new file mode 100644 index 000000000..5cdbbd890 --- /dev/null +++ b/applications/plugins/ifttt/ifttt_virtual_button.c @@ -0,0 +1,109 @@ +#include "ifttt_virtual_button.h" + +static bool ifttt_virtual_button_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + VirtualButtonApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool ifttt_virtual_button_back_event_callback(void* context) { + furi_assert(context); + VirtualButtonApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void ifttt_virtual_button_tick_event_callback(void* context) { + furi_assert(context); + VirtualButtonApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +VirtualButtonApp* ifttt_virtual_button_app_alloc(uint32_t first_scene) { + VirtualButtonApp* app = malloc(sizeof(VirtualButtonApp)); + + // Records + app->gui = furi_record_open(RECORD_GUI); + app->power = furi_record_open(RECORD_POWER); + + // View dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&virtual_button_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, ifttt_virtual_button_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, ifttt_virtual_button_back_event_callback); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, ifttt_virtual_button_tick_event_callback, 2000); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Views + app->sen_view = send_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + VirtualButtonAppViewSendView, + send_view_get_view(app->sen_view)); + + app->modul_view = module_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + VirtualButtonAppViewModuleView, + module_view_get_view(app->modul_view)); + + app->reboo_view = reboot_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + VirtualButtonAppViewRebootView, + reboot_view_get_view(app->reboo_view)); + + app->rese_view = reset_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + VirtualButtonAppViewResetView, + reset_view_get_view(app->rese_view)); + + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, VirtualButtonAppViewSubmenu, submenu_get_view(app->submenu)); + app->dialog = dialog_ex_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, VirtualButtonAppViewDialog, dialog_ex_get_view(app->dialog)); + + // Set first scene + scene_manager_next_scene(app->scene_manager, first_scene); + return app; +} + +void ifttt_virtual_button_app_free(VirtualButtonApp* app) { + furi_assert(app); + // Views + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewSendView); + send_view_free(app->sen_view); + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewModuleView); + module_view_free(app->modul_view); + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewRebootView); + reboot_view_free(app->reboo_view); + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewResetView); + reset_view_free(app->rese_view); + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewSubmenu); + submenu_free(app->submenu); + view_dispatcher_remove_view(app->view_dispatcher, VirtualButtonAppViewDialog); + dialog_ex_free(app->dialog); + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + // Records + furi_record_close(RECORD_POWER); + furi_record_close(RECORD_GUI); + free(app); +} + +int32_t ifttt_virtual_button_app(void* p) { + UNUSED(p); + uint32_t first_scene = VirtualButtonAppSceneStart; + VirtualButtonApp* app = ifttt_virtual_button_app_alloc(first_scene); + view_dispatcher_run(app->view_dispatcher); + ifttt_virtual_button_app_free(app); + return 0; +} diff --git a/applications/plugins/ifttt/ifttt_virtual_button.h b/applications/plugins/ifttt/ifttt_virtual_button.h new file mode 100644 index 000000000..baded9370 --- /dev/null +++ b/applications/plugins/ifttt/ifttt_virtual_button.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "views/send_view.h" +#include "views/module_view.h" +#include "views/reboot_view.h" +#include "views/reset_view.h" +#include +#include + +#include "scenes/virtual_button_scene.h" + +typedef struct { + Power* power; + Gui* gui; + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + SendView* sen_view; + ModuleView* modul_view; + RebootView* reboo_view; + ResetView* rese_view; + Submenu* submenu; + DialogEx* dialog; + PowerInfo info; +} VirtualButtonApp; + +typedef enum { + VirtualButtonAppViewSendView, + VirtualButtonAppViewModuleView, + VirtualButtonAppViewRebootView, + VirtualButtonAppViewResetView, + VirtualButtonAppViewSubmenu, + VirtualButtonAppViewDialog, +} VirtualButtonAppView; diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene.c b/applications/plugins/ifttt/scenes/virtual_button_scene.c new file mode 100644 index 000000000..a75d822fc --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene.c @@ -0,0 +1,30 @@ +#include "virtual_button_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const virtual_button_on_enter_handlers[])(void*) = { +#include "virtual_button_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const virtual_button_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "virtual_button_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const virtual_button_on_exit_handlers[])(void* context) = { +#include "virtual_button_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers virtual_button_scene_handlers = { + .on_enter_handlers = virtual_button_on_enter_handlers, + .on_event_handlers = virtual_button_on_event_handlers, + .on_exit_handlers = virtual_button_on_exit_handlers, + .scene_num = VirtualButtonAppSceneNum, +}; diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene.h b/applications/plugins/ifttt/scenes/virtual_button_scene.h new file mode 100644 index 000000000..870807dee --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) VirtualButtonAppScene##id, +typedef enum { +#include "virtual_button_scene_config.h" + VirtualButtonAppSceneNum, +} VirtualButtonAppScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers virtual_button_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "virtual_button_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "virtual_button_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "virtual_button_scene_config.h" +#undef ADD_SCENE diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_config.h b/applications/plugins/ifttt/scenes/virtual_button_scene_config.h new file mode 100644 index 000000000..ca4c23435 --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_config.h @@ -0,0 +1,5 @@ +ADD_SCENE(virtual_button, start, Start) +ADD_SCENE(virtual_button, send_view, SendView) +ADD_SCENE(virtual_button, module_view, ModuleView) +ADD_SCENE(virtual_button, reboot_view, RebootView) +ADD_SCENE(virtual_button, reset_view, ResetView) \ No newline at end of file diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_module.c b/applications/plugins/ifttt/scenes/virtual_button_scene_module.c new file mode 100644 index 000000000..33d5ae0c2 --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_module.c @@ -0,0 +1,26 @@ +#include "../ifttt_virtual_button.h" + +static void virtual_button_scene_module_view_update_model(VirtualButtonApp* app) { + power_get_info(app->power, &app->info); +} + +void virtual_button_scene_module_view_on_enter(void* context) { + VirtualButtonApp* app = context; + virtual_button_scene_module_view_update_model(app); + view_dispatcher_switch_to_view(app->view_dispatcher, VirtualButtonAppViewModuleView); +} + +bool virtual_button_scene_module_view_on_event(void* context, SceneManagerEvent event) { + VirtualButtonApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + virtual_button_scene_module_view_update_model(app); + consumed = true; + } + return consumed; +} + +void virtual_button_scene_module_view_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_reboot.c b/applications/plugins/ifttt/scenes/virtual_button_scene_reboot.c new file mode 100644 index 000000000..15a65516e --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_reboot.c @@ -0,0 +1,26 @@ +#include "../ifttt_virtual_button.h" + +static void virtual_button_scene_reboot_view_update_model(VirtualButtonApp* app) { + power_get_info(app->power, &app->info); +} + +void virtual_button_scene_reboot_view_on_enter(void* context) { + VirtualButtonApp* app = context; + virtual_button_scene_reboot_view_update_model(app); + view_dispatcher_switch_to_view(app->view_dispatcher, VirtualButtonAppViewRebootView); +} + +bool virtual_button_scene_reboot_view_on_event(void* context, SceneManagerEvent event) { + VirtualButtonApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + virtual_button_scene_reboot_view_update_model(app); + consumed = true; + } + return consumed; +} + +void virtual_button_scene_reboot_view_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_reset.c b/applications/plugins/ifttt/scenes/virtual_button_scene_reset.c new file mode 100644 index 000000000..675778b8f --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_reset.c @@ -0,0 +1,26 @@ +#include "../ifttt_virtual_button.h" + +static void virtual_button_scene_reset_view_update_model(VirtualButtonApp* app) { + power_get_info(app->power, &app->info); +} + +void virtual_button_scene_reset_view_on_enter(void* context) { + VirtualButtonApp* app = context; + virtual_button_scene_reset_view_update_model(app); + view_dispatcher_switch_to_view(app->view_dispatcher, VirtualButtonAppViewResetView); +} + +bool virtual_button_scene_reset_view_on_event(void* context, SceneManagerEvent event) { + VirtualButtonApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + virtual_button_scene_reset_view_update_model(app); + consumed = true; + } + return consumed; +} + +void virtual_button_scene_reset_view_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_send.c b/applications/plugins/ifttt/scenes/virtual_button_scene_send.c new file mode 100644 index 000000000..caa23fadf --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_send.c @@ -0,0 +1,26 @@ +#include "../ifttt_virtual_button.h" + +static void virtual_button_scene_send_view_update_model(VirtualButtonApp* app) { + power_get_info(app->power, &app->info); +} + +void virtual_button_scene_send_view_on_enter(void* context) { + VirtualButtonApp* app = context; + virtual_button_scene_send_view_update_model(app); + view_dispatcher_switch_to_view(app->view_dispatcher, VirtualButtonAppViewSendView); +} + +bool virtual_button_scene_send_view_on_event(void* context, SceneManagerEvent event) { + VirtualButtonApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + virtual_button_scene_send_view_update_model(app); + consumed = true; + } + return consumed; +} + +void virtual_button_scene_send_view_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/plugins/ifttt/scenes/virtual_button_scene_start.c b/applications/plugins/ifttt/scenes/virtual_button_scene_start.c new file mode 100644 index 000000000..6f7a11350 --- /dev/null +++ b/applications/plugins/ifttt/scenes/virtual_button_scene_start.c @@ -0,0 +1,73 @@ +#include "../ifttt_virtual_button.h" + +enum VirtualButtonSubmenuIndex { + VirtualButtonSubmenuIndexSendView, + VirtualButtonSubmenuIndexModuleView, + VirtualButtonSubmenuIndexRebootView, + VirtualButtonSubmenuIndexResetView, +}; + +static void virtual_button_scene_start_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + VirtualButtonApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void virtual_button_scene_start_on_enter(void* context) { + VirtualButtonApp* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, + "Send IFTTT command", + VirtualButtonSubmenuIndexSendView, + virtual_button_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "Configure module", + VirtualButtonSubmenuIndexModuleView, + virtual_button_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "Reboot module", + VirtualButtonSubmenuIndexRebootView, + virtual_button_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "Reset module", + VirtualButtonSubmenuIndexResetView, + virtual_button_scene_start_submenu_callback, + app); + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, VirtualButtonAppSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, VirtualButtonAppViewSubmenu); +} + +bool virtual_button_scene_start_on_event(void* context, SceneManagerEvent event) { + VirtualButtonApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == VirtualButtonSubmenuIndexSendView) { + scene_manager_next_scene(app->scene_manager, VirtualButtonAppSceneSendView); + }else if(event.event == VirtualButtonSubmenuIndexModuleView) { + scene_manager_next_scene(app->scene_manager, VirtualButtonAppSceneModuleView); + }else if(event.event == VirtualButtonSubmenuIndexRebootView) { + scene_manager_next_scene(app->scene_manager, VirtualButtonAppSceneRebootView); + }else if(event.event == VirtualButtonSubmenuIndexResetView) { + scene_manager_next_scene(app->scene_manager, VirtualButtonAppSceneResetView); + } + scene_manager_set_scene_state(app->scene_manager, VirtualButtonAppSceneStart, event.event); + consumed = true; + } + return consumed; +} + +void virtual_button_scene_start_on_exit(void* context) { + VirtualButtonApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/plugins/ifttt/views/module_view.c b/applications/plugins/ifttt/views/module_view.c new file mode 100644 index 000000000..0112a09d1 --- /dev/null +++ b/applications/plugins/ifttt/views/module_view.c @@ -0,0 +1,154 @@ +#include "module_view.h" +#include +#include +#include +#include +#include + +#define MODULE_CONTROL_COMMAND_CONFIG_ON 'c' +#define MODULE_CONTROL_COMMAND_CONFIG_OFF 'd' +#define FLIPPERZERO_SERIAL_BAUD 115200 + +bool configState; + +typedef enum ESerialCommand +{ + ESerialCommand_Config_On, + ESerialCommand_Config_Off +} ESerialCommand; + +struct ModuleView { + View* view; +}; + +typedef struct { + bool right_pressed; + bool connected; +} ModuleViewModel; + +/* +static void Shake(void) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_single_vibro); + furi_record_close(RECORD_NOTIFICATION); +} +*/ + +void send_serial_command_module(ESerialCommand command) +{ + uint8_t data[1] = { 0 }; + + switch(command) + { + case ESerialCommand_Config_On: + data[0] = MODULE_CONTROL_COMMAND_CONFIG_ON; + break; + case ESerialCommand_Config_Off: + data[0] = MODULE_CONTROL_COMMAND_CONFIG_OFF; + break; + default: + return; + }; + + furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); +} + +static void module_view_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + ModuleViewModel* model = context; + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "CONFIGURE MODULE"); + canvas_draw_line(canvas, 0, 10, 128, 10); + canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Press right to start the"); + canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignTop, "configurator and connect"); + canvas_draw_str_aligned(canvas, 64, 35, AlignCenter, AlignTop, "to ip 192.168.4.1 or press"); + canvas_draw_str_aligned(canvas, 64, 45, AlignCenter, AlignTop, "and hold back to return"); + canvas_draw_str_aligned(canvas, 64, 55, AlignCenter, AlignTop, "to the menu"); + + if(configState == false){ + send_serial_command_module(ESerialCommand_Config_On); + configState = true; + } + + // Right + if(model->right_pressed) { + } +} + +static void module_view_process(ModuleView* module_view, InputEvent* event) { + with_view_model( + module_view->view, (ModuleViewModel * model) { + if(event->type == InputTypePress) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeRelease) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyBack) { + } + } + return true; + }); +} + +static bool module_view_input_callback(InputEvent* event, void* context) { + furi_assert(context); + ModuleView* module_view = context; + bool consumed = false; + + if(event->type == InputTypeLong && event->key == InputKeyBack) { + send_serial_command_module(ESerialCommand_Config_Off); + configState = false; + } else { + module_view_process(module_view, event); + consumed = true; + } + + return consumed; +} + +ModuleView* module_view_alloc() { + ModuleView* module_view = malloc(sizeof(ModuleView)); + module_view->view = view_alloc(); + view_set_context(module_view->view, module_view); + view_allocate_model(module_view->view, ViewModelTypeLocking, sizeof(ModuleViewModel)); + view_set_draw_callback(module_view->view, module_view_draw_callback); + view_set_input_callback(module_view->view, module_view_input_callback); + furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); + configState = false; + return module_view; +} + +void module_view_free(ModuleView* module_view) { + furi_assert(module_view); + view_free(module_view->view); + free(module_view); +} + +View* module_view_get_view(ModuleView* module_view) { + furi_assert(module_view); + return module_view->view; +} + +void module_view_set_data(ModuleView* module_view, bool connected) { + furi_assert(module_view); + with_view_model( + module_view->view, (ModuleViewModel * model) { + model->connected = connected; + return true; + }); +} \ No newline at end of file diff --git a/applications/plugins/ifttt/views/module_view.h b/applications/plugins/ifttt/views/module_view.h new file mode 100644 index 000000000..d486aa9fa --- /dev/null +++ b/applications/plugins/ifttt/views/module_view.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct ModuleView ModuleView; + +ModuleView* module_view_alloc(); + +void module_view_free(ModuleView* module_view); + +View* module_view_get_view(ModuleView* module_view); \ No newline at end of file diff --git a/applications/plugins/ifttt/views/reboot_view.c b/applications/plugins/ifttt/views/reboot_view.c new file mode 100644 index 000000000..0ad0eff48 --- /dev/null +++ b/applications/plugins/ifttt/views/reboot_view.c @@ -0,0 +1,138 @@ +#include "reboot_view.h" +#include +#include +#include +#include +#include + +#define MODULE_CONTROL_COMMAND_REBOOT 'r' +#define FLIPPERZERO_SERIAL_BAUD 115200 + +typedef enum ESerialCommand +{ + ESerialCommand_Reboot +} ESerialCommand; + +struct RebootView { + View* view; +}; + +typedef struct { + bool right_pressed; + bool connected; +} RebootViewModel; + +static void Shake(void) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_single_vibro); + furi_record_close(RECORD_NOTIFICATION); +} + +void send_serial_command_reboot(ESerialCommand command) +{ + uint8_t data[1] = { 0 }; + + switch(command) + { + case ESerialCommand_Reboot: + data[0] = MODULE_CONTROL_COMMAND_REBOOT; + break; + default: + return; + }; + + furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); +} + +static void reboot_view_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + RebootViewModel* model = context; + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "REBOOT MODULE"); + canvas_draw_line(canvas, 0, 10, 128, 10); + canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Press right to restart the"); + canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignTop, "module or press and hold"); + canvas_draw_str_aligned(canvas, 64, 35, AlignCenter, AlignTop, "back to return to the menu"); + + // Right + if(model->right_pressed) { + } +} + +static void reboot_view_process(RebootView* reboot_view, InputEvent* event) { + with_view_model( + reboot_view->view, (RebootViewModel * model) { + if(event->type == InputTypePress) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + Shake(); + send_serial_command_reboot(ESerialCommand_Reboot); + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeRelease) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyBack) { + } + } + return true; + }); +} + +static bool reboot_view_input_callback(InputEvent* event, void* context) { + furi_assert(context); + RebootView* reboot_view = context; + bool consumed = false; + + if(event->type == InputTypeLong && event->key == InputKeyBack) { + } else { + reboot_view_process(reboot_view, event); + consumed = true; + } + + return consumed; +} + +RebootView* reboot_view_alloc() { + RebootView* reboot_view = malloc(sizeof(RebootView)); + reboot_view->view = view_alloc(); + view_set_context(reboot_view->view, reboot_view); + view_allocate_model(reboot_view->view, ViewModelTypeLocking, sizeof(RebootViewModel)); + view_set_draw_callback(reboot_view->view, reboot_view_draw_callback); + view_set_input_callback(reboot_view->view, reboot_view_input_callback); + furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); + + return reboot_view; +} + +void reboot_view_free(RebootView* reboot_view) { + furi_assert(reboot_view); + view_free(reboot_view->view); + free(reboot_view); +} + +View* reboot_view_get_view(RebootView* reboot_view) { + furi_assert(reboot_view); + return reboot_view->view; +} + +void reboot_view_set_data(RebootView* reboot_view, bool connected) { + furi_assert(reboot_view); + with_view_model( + reboot_view->view, (RebootViewModel * model) { + model->connected = connected; + return true; + }); +} \ No newline at end of file diff --git a/applications/plugins/ifttt/views/reboot_view.h b/applications/plugins/ifttt/views/reboot_view.h new file mode 100644 index 000000000..28d5841f1 --- /dev/null +++ b/applications/plugins/ifttt/views/reboot_view.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct RebootView RebootView; + +RebootView* reboot_view_alloc(); + +void reboot_view_free(RebootView* reboot_view); + +View* reboot_view_get_view(RebootView* reboot_view); \ No newline at end of file diff --git a/applications/plugins/ifttt/views/reset_view.c b/applications/plugins/ifttt/views/reset_view.c new file mode 100644 index 000000000..d09bd87ff --- /dev/null +++ b/applications/plugins/ifttt/views/reset_view.c @@ -0,0 +1,138 @@ +#include "reset_view.h" +#include +#include +#include +#include +#include + +#define MODULE_CONTROL_COMMAND_RESET 'a' +#define FLIPPERZERO_SERIAL_BAUD 115200 + +typedef enum ESerialCommand +{ + ESerialCommand_Reset +} ESerialCommand; + +struct ResetView { + View* view; +}; + +typedef struct { + bool right_pressed; + bool connected; +} ResetViewModel; + +static void Shake(void) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_single_vibro); + furi_record_close(RECORD_NOTIFICATION); +} + +void send_serial_command_reset(ESerialCommand command) +{ + uint8_t data[1] = { 0 }; + + switch(command) + { + case ESerialCommand_Reset: + data[0] = MODULE_CONTROL_COMMAND_RESET; + break; + default: + return; + }; + + furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); +} + +static void reset_view_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + ResetViewModel* model = context; + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "RESET MODULE"); + canvas_draw_line(canvas, 0, 10, 128, 10); + canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Press right to reset"); + canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignTop, "module or press and hold"); + canvas_draw_str_aligned(canvas, 64, 35, AlignCenter, AlignTop, "back to return to the menu"); + + // Right + if(model->right_pressed) { + } +} + +static void reset_view_process(ResetView* reset_view, InputEvent* event) { + with_view_model( + reset_view->view, (ResetViewModel * model) { + if(event->type == InputTypePress) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + Shake(); + send_serial_command_reset(ESerialCommand_Reset); + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeRelease) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyBack) { + } + } + return true; + }); +} + +static bool reset_view_input_callback(InputEvent* event, void* context) { + furi_assert(context); + ResetView* reset_view = context; + bool consumed = false; + + if(event->type == InputTypeLong && event->key == InputKeyBack) { + } else { + reset_view_process(reset_view, event); + consumed = true; + } + + return consumed; +} + +ResetView* reset_view_alloc() { + ResetView* reset_view = malloc(sizeof(ResetView)); + reset_view->view = view_alloc(); + view_set_context(reset_view->view, reset_view); + view_allocate_model(reset_view->view, ViewModelTypeLocking, sizeof(ResetViewModel)); + view_set_draw_callback(reset_view->view, reset_view_draw_callback); + view_set_input_callback(reset_view->view, reset_view_input_callback); + furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); + + return reset_view; +} + +void reset_view_free(ResetView* reset_view) { + furi_assert(reset_view); + view_free(reset_view->view); + free(reset_view); +} + +View* reset_view_get_view(ResetView* reset_view) { + furi_assert(reset_view); + return reset_view->view; +} + +void reset_view_set_data(ResetView* reset_view, bool connected) { + furi_assert(reset_view); + with_view_model( + reset_view->view, (ResetViewModel * model) { + model->connected = connected; + return true; + }); +} \ No newline at end of file diff --git a/applications/plugins/ifttt/views/reset_view.h b/applications/plugins/ifttt/views/reset_view.h new file mode 100644 index 000000000..c71aad77d --- /dev/null +++ b/applications/plugins/ifttt/views/reset_view.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct ResetView ResetView; + +ResetView* reset_view_alloc(); + +void reset_view_free(ResetView* reset_view); + +View* reset_view_get_view(ResetView* reset_view); \ No newline at end of file diff --git a/applications/plugins/ifttt/views/send_view.c b/applications/plugins/ifttt/views/send_view.c new file mode 100644 index 000000000..4c96fa774 --- /dev/null +++ b/applications/plugins/ifttt/views/send_view.c @@ -0,0 +1,138 @@ +#include "send_view.h" +#include +#include +#include +#include +#include + +#define MODULE_CONTROL_COMMAND_SEND 's' +#define FLIPPERZERO_SERIAL_BAUD 115200 + +typedef enum ESerialCommand +{ + ESerialCommand_Send +} ESerialCommand; + +struct SendView { + View* view; +}; + +typedef struct { + bool right_pressed; + bool connected; +} SendViewModel; + +static void Shake(void) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_single_vibro); + furi_record_close(RECORD_NOTIFICATION); +} + +void send_serial_command_send(ESerialCommand command) +{ + uint8_t data[1] = { 0 }; + + switch(command) + { + case ESerialCommand_Send: + data[0] = MODULE_CONTROL_COMMAND_SEND; + break; + default: + return; + }; + + furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); +} + +static void send_view_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + SendViewModel* model = context; + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "SEND MODULE"); + canvas_draw_line(canvas, 0, 10, 128, 10); + canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Press right to send IFTTT"); + canvas_draw_str_aligned(canvas, 64, 25, AlignCenter, AlignTop, "command or press and hold"); + canvas_draw_str_aligned(canvas, 64, 35, AlignCenter, AlignTop, "back to return to the menu"); + + // Right + if(model->right_pressed) { + } +} + +static void send_view_process(SendView* send_view, InputEvent* event) { + with_view_model( + send_view->view, (SendViewModel * model) { + if(event->type == InputTypePress) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = true; + Shake(); + send_serial_command_send(ESerialCommand_Send); + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeRelease) { + if(event->key == InputKeyUp) { + } else if(event->key == InputKeyDown) { + } else if(event->key == InputKeyLeft) { + } else if(event->key == InputKeyRight) { + model->right_pressed = false; + } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyBack) { + } + } else if(event->type == InputTypeShort) { + if(event->key == InputKeyBack) { + } + } + return true; + }); +} + +static bool send_view_input_callback(InputEvent* event, void* context) { + furi_assert(context); + SendView* send_view = context; + bool consumed = false; + + if(event->type == InputTypeLong && event->key == InputKeyBack) { + } else { + send_view_process(send_view, event); + consumed = true; + } + + return consumed; +} + +SendView* send_view_alloc() { + SendView* send_view = malloc(sizeof(SendView)); + send_view->view = view_alloc(); + view_set_context(send_view->view, send_view); + view_allocate_model(send_view->view, ViewModelTypeLocking, sizeof(SendViewModel)); + view_set_draw_callback(send_view->view, send_view_draw_callback); + view_set_input_callback(send_view->view, send_view_input_callback); + furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD); + + return send_view; +} + +void send_view_free(SendView* send_view) { + furi_assert(send_view); + view_free(send_view->view); + free(send_view); +} + +View* send_view_get_view(SendView* send_view) { + furi_assert(send_view); + return send_view->view; +} + +void send_view_set_data(SendView* send_view, bool connected) { + furi_assert(send_view); + with_view_model( + send_view->view, (SendViewModel * model) { + model->connected = connected; + return true; + }); +} \ No newline at end of file diff --git a/applications/plugins/ifttt/views/send_view.h b/applications/plugins/ifttt/views/send_view.h new file mode 100644 index 000000000..4b1944dd4 --- /dev/null +++ b/applications/plugins/ifttt/views/send_view.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct SendView SendView; + +SendView* send_view_alloc(); + +void send_view_free(SendView* send_view); + +View* send_view_get_view(SendView* send_view); \ No newline at end of file