From d80edba8916210248cb2f0107f872cddc1dceb95 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Mon, 25 Jul 2022 17:16:45 +0300 Subject: [PATCH] RPC App: state message and GUI update (#1423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RPC App: state message and GUI update * Protobuf submodule update Co-authored-by: SG Co-authored-by: あく --- applications/ibutton/ibutton.c | 18 ++++-- applications/ibutton/ibutton_custom_event.h | 1 + .../ibutton/scenes/ibutton_scene_rpc.c | 39 +++++++++++-- applications/infrared/infrared.c | 17 ++++-- applications/infrared/infrared_custom_event.h | 1 + .../infrared/scenes/infrared_scene_rpc.c | 12 +++- applications/lfrfid/lfrfid_app.cpp | 2 + .../lfrfid/scene/lfrfid_app_scene_rpc.cpp | 23 +++++++- applications/nfc/helpers/nfc_custom_event.h | 1 + applications/nfc/nfc.c | 32 ++++++---- applications/nfc/scenes/nfc_scene_rpc.c | 25 ++++++-- applications/rpc/rpc_app.c | 29 +++++++++- applications/rpc/rpc_app.h | 4 ++ .../subghz/helpers/subghz_custom_event.h | 2 + applications/subghz/scenes/subghz_scene_rpc.c | 33 ++++++++--- applications/subghz/subghz.c | 58 ++++++++++++++----- assets/protobuf | 2 +- 17 files changed, 237 insertions(+), 62 deletions(-) diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index 0f54dc3e..0f14137c 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -118,6 +118,8 @@ static bool ibutton_rpc_command_callback(RpcAppSystemEvent event, const char* ar string_set_str(ibutton->file_path, arg); if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); + view_dispatcher_send_custom_event( + ibutton->view_dispatcher, iButtonCustomEventRpcLoad); result = true; } } @@ -162,8 +164,6 @@ iButton* ibutton_alloc() { ibutton->view_dispatcher, ibutton_tick_event_callback, 100); ibutton->gui = furi_record_open("gui"); - view_dispatcher_attach_to_gui( - ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); ibutton->storage = furi_record_open("storage"); ibutton->dialogs = furi_record_open("dialogs"); @@ -373,6 +373,7 @@ int32_t ibutton_app(void* p) { ibutton->rpc_ctx = (void*)rpc_ctx; rpc_mode = true; rpc_system_app_set_callback(ibutton->rpc_ctx, ibutton_rpc_command_callback, ibutton); + rpc_system_app_send_started(ibutton->rpc_ctx); } else { string_set_str(ibutton->file_path, (const char*)p); if(ibutton_load_key_data(ibutton, ibutton->file_path, true)) { @@ -383,17 +384,24 @@ int32_t ibutton_app(void* p) { } if(rpc_mode) { + view_dispatcher_attach_to_gui( + ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc); - } else if(key_loaded) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); } else { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); + view_dispatcher_attach_to_gui( + ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); + if(key_loaded) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + } else { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); + } } view_dispatcher_run(ibutton->view_dispatcher); if(ibutton->rpc_ctx) { rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(ibutton->rpc_ctx); } ibutton_free(ibutton); return 0; diff --git a/applications/ibutton/ibutton_custom_event.h b/applications/ibutton/ibutton_custom_event.h index 1706e00f..25dfc31d 100644 --- a/applications/ibutton/ibutton_custom_event.h +++ b/applications/ibutton/ibutton_custom_event.h @@ -10,5 +10,6 @@ enum iButtonCustomEvent { iButtonCustomEventWorkerEmulated, iButtonCustomEventWorkerRead, + iButtonCustomEventRpcLoad, iButtonCustomEventRpcExit, }; diff --git a/applications/ibutton/scenes/ibutton_scene_rpc.c b/applications/ibutton/scenes/ibutton_scene_rpc.c index ceeca017..14f7df63 100644 --- a/applications/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/ibutton/scenes/ibutton_scene_rpc.c @@ -3,12 +3,14 @@ void ibutton_scene_rpc_on_enter(void* context) { iButton* ibutton = context; - Widget* widget = ibutton->widget; + Popup* popup = ibutton->popup; - widget_add_text_box_element( - widget, 0, 0, 128, 28, AlignCenter, AlignCenter, "RPC mode", false); + popup_set_header(popup, "iButton", 82, 28, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + popup_set_icon(popup, 2, 14, &I_iButtonKey_49x44); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); notification_message(ibutton->notifications, &sequence_display_backlight_on); } @@ -17,12 +19,31 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { UNUSED(context); UNUSED(event); iButton* ibutton = context; + Popup* popup = ibutton->popup; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { consumed = true; - if(event.event == iButtonCustomEventRpcExit) { + if(event.event == iButtonCustomEventRpcLoad) { + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } + + if(!string_empty_p(key_name)) { + ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name)); + } else { + ibutton_text_store_set(ibutton, "emulating"); + } + popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); + + ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + + string_clear(key_name); + } else if(event.event == iButtonCustomEventRpcExit) { + ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); view_dispatcher_stop(ibutton->view_dispatcher); } } @@ -32,5 +53,11 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { void ibutton_scene_rpc_on_exit(void* context) { iButton* ibutton = context; - widget_reset(ibutton->widget); + Popup* popup = ibutton->popup; + + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + + ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); } diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index 62206116..1dd0dfa6 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -65,6 +65,8 @@ static bool infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); infrared_worker_tx_set_signal_sent_callback( infrared->worker, infrared_signal_sent_callback, infrared); + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeRpcLoaded); } } else if(event == RpcAppEventButtonPress) { if(arg) { @@ -141,7 +143,6 @@ static Infrared* infrared_alloc() { infrared->gui = furi_record_open("gui"); ViewDispatcher* view_dispatcher = infrared->view_dispatcher; - view_dispatcher_attach_to_gui(view_dispatcher, infrared->gui, ViewDispatcherTypeFullscreen); view_dispatcher_enable_queue(view_dispatcher); view_dispatcher_set_event_callback_context(view_dispatcher, infrared); view_dispatcher_set_custom_event_callback(view_dispatcher, infrared_custom_event_callback); @@ -202,6 +203,7 @@ static void infrared_free(Infrared* infrared) { if(infrared->rpc_ctx) { rpc_system_app_set_callback(infrared->rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(infrared->rpc_ctx); infrared->rpc_ctx = NULL; } @@ -434,6 +436,7 @@ int32_t infrared_app(void* p) { infrared->rpc_ctx = (void*)rpc_ctx; rpc_system_app_set_callback( infrared->rpc_ctx, infrared_rpc_command_callback, infrared); + rpc_system_app_send_started(infrared->rpc_ctx); is_rpc_mode = true; } else { string_set_str(infrared->file_path, (const char*)p); @@ -447,11 +450,17 @@ int32_t infrared_app(void* p) { } if(is_rpc_mode) { + view_dispatcher_attach_to_gui( + infrared->view_dispatcher, infrared->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(infrared->scene_manager, InfraredSceneRpc); - } else if(is_remote_loaded) { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); } else { - scene_manager_next_scene(infrared->scene_manager, InfraredSceneStart); + view_dispatcher_attach_to_gui( + infrared->view_dispatcher, infrared->gui, ViewDispatcherTypeFullscreen); + if(is_remote_loaded) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); + } else { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneStart); + } } view_dispatcher_run(infrared->view_dispatcher); diff --git a/applications/infrared/infrared_custom_event.h b/applications/infrared/infrared_custom_event.h index 46d75a9e..29bd61f1 100644 --- a/applications/infrared/infrared_custom_event.h +++ b/applications/infrared/infrared_custom_event.h @@ -14,6 +14,7 @@ enum InfraredCustomEventType { InfraredCustomEventTypePopupClosed, InfraredCustomEventTypeButtonSelected, InfraredCustomEventTypeBackPressed, + InfraredCustomEventTypeRpcLoaded, }; #pragma pack(push, 1) diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index 3cab9f80..e31e7fb6 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -5,12 +5,14 @@ void infrared_scene_rpc_on_enter(void* context) { Infrared* infrared = context; Popup* popup = infrared->popup; - popup_set_text(popup, "Rpc mode", 64, 28, AlignCenter, AlignCenter); + popup_set_header(popup, "Infrared", 82, 28, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + + popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon popup_set_context(popup, context); popup_set_callback(popup, infrared_popup_closed_callback); - infrared_play_notification_message(infrared, InfraredNotificationMessageYellowOn); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); notification_message(infrared->notifications, &sequence_display_backlight_on); @@ -26,6 +28,12 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(infrared->view_dispatcher); } else if(event.event == InfraredCustomEventTypePopupClosed) { view_dispatcher_stop(infrared->view_dispatcher); + } else if(event.event == InfraredCustomEventTypeRpcLoaded) { + const char* remote_name = infrared_remote_get_name(infrared->remote); + + infrared_text_store_set(infrared, 0, "loaded\n%s", remote_name); + popup_set_text( + infrared->popup, infrared->text_store[0], 82, 32, AlignCenter, AlignTop); } } return consumed; diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index c491cf40..2ba36ea3 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -44,6 +44,7 @@ LfRfidApp::~LfRfidApp() { string_clear(file_path); if(rpc_ctx) { rpc_system_app_set_callback(rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(rpc_ctx); } } @@ -91,6 +92,7 @@ void LfRfidApp::run(void* _args) { if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr; rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this); + rpc_system_app_send_started(rpc_ctx); scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc()); scene_controller.process(100, SceneType::Rpc); } else { diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp index 80d47934..bc070ce6 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp @@ -2,10 +2,24 @@ #include #include +static const NotificationSequence sequence_blink_start_magenta = { + &message_blink_start_10, + &message_blink_set_color_magenta, + &message_do_not_reset, + NULL, +}; + +static const NotificationSequence sequence_blink_stop = { + &message_blink_stop, + NULL, +}; + void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) { auto popup = app->view_controller.get(); - popup->set_header("RPC Mode", 64, 30, AlignCenter, AlignTop); + popup->set_header("LF RFID", 89, 30, AlignCenter, AlignTop); + popup->set_text("RPC mode", 89, 43, AlignCenter, AlignTop); + popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61); app->view_controller.switch_to(); @@ -23,8 +37,14 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { view_event.type = LfRfidApp::EventType::Back; app->view_controller.send_event(&view_event); } else if(event->type == LfRfidApp::EventType::EmulateStart) { + auto popup = app->view_controller.get(); consumed = true; emulating = true; + + app->text_store.set("emulating\n%s", app->worker.key.get_name()); + popup->set_text(app->text_store.text, 89, 43, AlignCenter, AlignTop); + + notification_message(app->notification, &sequence_blink_start_magenta); } return consumed; } @@ -32,6 +52,7 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) { void LfRfidAppSceneRpc::on_exit(LfRfidApp* app) { if(emulating) { app->worker.stop_emulate(); + notification_message(app->notification, &sequence_blink_stop); } app->view_controller.get()->clean(); } diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h index 5de44001..b877732a 100644 --- a/applications/nfc/helpers/nfc_custom_event.h +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -9,4 +9,5 @@ enum NfcCustomEvent { NfcCustomEventByteInputDone, NfcCustomEventTextInputDone, NfcCustomEventDictAttackDone, + NfcCustomEventRpcLoad, }; diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 0dc4b3ae..fb739c61 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -31,6 +31,7 @@ void nfc_rpc_exit_callback(Nfc* nfc) { } if(nfc->rpc_ctx) { rpc_system_app_set_callback(nfc->rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(nfc->rpc_ctx); nfc->rpc_ctx = NULL; } } @@ -82,6 +83,7 @@ static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, v nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc); } nfc->rpc_state = NfcRpcStateEmulating; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); result = true; } } @@ -107,7 +109,6 @@ Nfc* nfc_alloc() { // Open GUI record nfc->gui = furi_record_open("gui"); - view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); // Open Notification record nfc->notifications = furi_record_open("notification"); @@ -291,21 +292,30 @@ int32_t nfc_app(void* p) { if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { nfc->rpc_ctx = (void*)rpc_ctx; rpc_system_app_set_callback(nfc->rpc_ctx, nfc_rpc_command_callback, nfc); + rpc_system_app_send_started(nfc->rpc_ctx); + view_dispatcher_attach_to_gui( + nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(nfc->scene_manager, NfcSceneRpc); - } else if(nfc_device_load(nfc->dev, p, true)) { - if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic); - } else { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); - } } else { - // Exit app - view_dispatcher_stop(nfc->view_dispatcher); + view_dispatcher_attach_to_gui( + nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); + if(nfc_device_load(nfc->dev, p, true)) { + if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); + } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + } + } else { + // Exit app + view_dispatcher_stop(nfc->view_dispatcher); + } } nfc_device_set_loading_callback(nfc->dev, NULL, nfc); } else { + view_dispatcher_attach_to_gui( + nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); scene_manager_next_scene(nfc->scene_manager, NfcSceneStart); } diff --git a/applications/nfc/scenes/nfc_scene_rpc.c b/applications/nfc/scenes/nfc_scene_rpc.c index b94bf424..582dff8e 100644 --- a/applications/nfc/scenes/nfc_scene_rpc.c +++ b/applications/nfc/scenes/nfc_scene_rpc.c @@ -2,24 +2,33 @@ void nfc_scene_rpc_on_enter(void* context) { Nfc* nfc = context; - Widget* widget = nfc->widget; + Popup* popup = nfc->popup; - widget_add_text_box_element( - widget, 0, 0, 128, 28, AlignCenter, AlignCenter, "RPC mode", false); + popup_set_header(popup, "NFC", 82, 28, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + + popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); notification_message(nfc->notifications, &sequence_display_backlight_on); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; + Popup* popup = nfc->popup; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == NfcCustomEventViewExit) { view_dispatcher_stop(nfc->view_dispatcher); + nfc_blink_stop(nfc); + } else if(event.event == NfcCustomEventRpcLoad) { + nfc_blink_start(nfc); + + nfc_text_store_set(nfc, "emulating\n%s", nfc->dev->dev_name); + popup_set_text(popup, nfc->text_store, 82, 32, AlignCenter, AlignTop); } } return consumed; @@ -27,8 +36,12 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { void nfc_scene_rpc_on_exit(void* context) { Nfc* nfc = context; + Popup* popup = nfc->popup; nfc_rpc_exit_callback(nfc); + nfc_blink_stop(nfc); - widget_reset(nfc->widget); + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); } diff --git a/applications/rpc/rpc_app.c b/applications/rpc/rpc_app.c index 84cb5410..525eedcf 100644 --- a/applications/rpc/rpc_app.c +++ b/applications/rpc/rpc_app.c @@ -12,6 +12,7 @@ struct RpcAppSystem { RpcSession* session; RpcAppSystemCallback app_callback; void* app_context; + PB_Main* state_msg; FuriTimer* timer; }; @@ -96,7 +97,7 @@ static void rpc_system_app_lock_status_process(const PB_Main* request, void* con pb_release(&PB_Main_msg, &response); } -static void rpc_system_app_exit(const PB_Main* request, void* context) { +static void rpc_system_app_exit_request(const PB_Main* request, void* context) { furi_assert(request); furi_assert(context); @@ -194,6 +195,24 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context) rpc_send_and_release_empty(session, request->command_id, status); } +void rpc_system_app_send_started(RpcAppSystem* rpc_app) { + furi_assert(rpc_app); + RpcSession* session = rpc_app->session; + furi_assert(session); + + rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_STARTED; + rpc_send(session, rpc_app->state_msg); +} + +void rpc_system_app_send_exited(RpcAppSystem* rpc_app) { + furi_assert(rpc_app); + RpcSession* session = rpc_app->session; + furi_assert(session); + + rpc_app->state_msg->content.app_state_response.state = PB_App_AppState_APP_CLOSED; + rpc_send(session, rpc_app->state_msg); +} + void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx) { furi_assert(rpc_app); @@ -209,6 +228,11 @@ void* rpc_system_app_alloc(RpcSession* session) { rpc_app->timer = furi_timer_alloc(rpc_system_app_timer_callback, FuriTimerTypeOnce, rpc_app); + // App exit message + rpc_app->state_msg = malloc(sizeof(PB_Main)); + rpc_app->state_msg->which_content = PB_Main_app_state_response_tag; + rpc_app->state_msg->command_status = PB_CommandStatus_OK; + RpcHandler rpc_handler = { .message_handler = NULL, .decode_submessage = NULL, @@ -221,7 +245,7 @@ void* rpc_system_app_alloc(RpcSession* session) { rpc_handler.message_handler = rpc_system_app_lock_status_process; rpc_add_handler(session, PB_Main_app_lock_status_request_tag, &rpc_handler); - rpc_handler.message_handler = rpc_system_app_exit; + rpc_handler.message_handler = rpc_system_app_exit_request; rpc_add_handler(session, PB_Main_app_exit_request_tag, &rpc_handler); rpc_handler.message_handler = rpc_system_app_load_file; @@ -247,5 +271,6 @@ void rpc_system_app_free(void* context) { rpc_app->app_callback(RpcAppEventSessionClose, NULL, rpc_app->app_context); } + free(rpc_app->state_msg); free(rpc_app); } diff --git a/applications/rpc/rpc_app.h b/applications/rpc/rpc_app.h index 396eef1a..4e00922f 100644 --- a/applications/rpc/rpc_app.h +++ b/applications/rpc/rpc_app.h @@ -19,6 +19,10 @@ typedef struct RpcAppSystem RpcAppSystem; void rpc_system_app_set_callback(RpcAppSystem* rpc_app, RpcAppSystemCallback callback, void* ctx); +void rpc_system_app_send_started(RpcAppSystem* rpc_app); + +void rpc_system_app_send_exited(RpcAppSystem* rpc_app); + #ifdef __cplusplus } #endif diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h index 05f0f492..801a8ae9 100644 --- a/applications/subghz/helpers/subghz_custom_event.h +++ b/applications/subghz/helpers/subghz_custom_event.h @@ -46,6 +46,8 @@ typedef enum { SubGhzCustomEventSceneExit, SubGhzCustomEventSceneStay, + SubGhzCustomEventSceneRpcLoad, + SubGhzCustomEventViewReceiverOK, SubGhzCustomEventViewReceiverConfig, SubGhzCustomEventViewReceiverBack, diff --git a/applications/subghz/scenes/subghz_scene_rpc.c b/applications/subghz/scenes/subghz_scene_rpc.c index c7573fda..844f5c16 100644 --- a/applications/subghz/scenes/subghz_scene_rpc.c +++ b/applications/subghz/scenes/subghz_scene_rpc.c @@ -2,24 +2,40 @@ void subghz_scene_rpc_on_enter(void* context) { SubGhz* subghz = context; - Widget* widget = subghz->widget; + Popup* popup = subghz->popup; - widget_add_text_box_element( - widget, 0, 0, 128, 28, AlignCenter, AlignCenter, "RPC mode", false); + popup_set_header(popup, "Sub-GHz", 82, 28, AlignCenter, AlignBottom); + popup_set_text(popup, "RPC mode", 82, 32, AlignCenter, AlignTop); + + popup_set_icon(popup, 2, 14, &I_Warning_30x23); // TODO: icon + + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdPopup); notification_message(subghz->notifications, &sequence_display_backlight_on); - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget); } bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; + Popup* popup = subghz->popup; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == SubGhzCustomEventSceneExit) { view_dispatcher_stop(subghz->view_dispatcher); + } else if(event.event == SubGhzCustomEventSceneRpcLoad) { + string_t file_name; + string_init(file_name); + path_extract_filename(subghz->file_path, file_name, true); + + snprintf( + subghz->file_name_tmp, + SUBGHZ_MAX_LEN_NAME, + "loaded\n%s", + string_get_cstr(file_name)); + popup_set_text(popup, subghz->file_name_tmp, 82, 32, AlignCenter, AlignTop); + + string_clear(file_name); } } return consumed; @@ -27,8 +43,9 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { void subghz_scene_rpc_on_exit(void* context) { SubGhz* subghz = context; + Popup* popup = subghz->popup; - //subghz_rpc_exit_callback(subghz); - - widget_reset(subghz->widget); + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); } diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 984ce472..76998eb0 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -5,6 +5,18 @@ #include "subghz_i.h" #include +static const NotificationSequence sequence_blink_start_magenta = { + &message_blink_start_10, + &message_blink_set_color_magenta, + &message_do_not_reset, + NULL, +}; + +static const NotificationSequence sequence_blink_stop = { + &message_blink_stop, + NULL, +}; + bool subghz_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubGhz* subghz = context; @@ -36,6 +48,7 @@ static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg if(event == RpcAppEventSessionClose) { rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); subghz->rpc_ctx = NULL; + notification_message(subghz->notifications, &sequence_blink_stop); view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneExit); if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { subghz_tx_stop(subghz); @@ -53,15 +66,19 @@ static bool subghz_rpc_command_callback(RpcAppSystemEvent event, const char* arg if(arg) { if(subghz_key_load(subghz, arg, false)) { string_set_str(subghz->file_path, arg); + view_dispatcher_send_custom_event( + subghz->view_dispatcher, SubGhzCustomEventSceneRpcLoad); result = true; } } } else if(event == RpcAppEventButtonPress) { if(subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { + notification_message(subghz->notifications, &sequence_blink_start_magenta); result = subghz_tx_start(subghz, subghz->txrx->fff_data); } } else if(event == RpcAppEventButtonRelease) { if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + notification_message(subghz->notifications, &sequence_blink_stop); subghz_tx_stop(subghz); subghz_sleep(subghz); result = true; @@ -83,8 +100,6 @@ SubGhz* subghz_alloc() { // View Dispatcher subghz->view_dispatcher = view_dispatcher_alloc(); view_dispatcher_enable_queue(subghz->view_dispatcher); - view_dispatcher_attach_to_gui( - subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); subghz->scene_manager = scene_manager_alloc(&subghz_scene_handlers, subghz); view_dispatcher_set_event_callback_context(subghz->view_dispatcher, subghz); @@ -218,6 +233,8 @@ void subghz_free(SubGhz* subghz) { if(subghz->rpc_ctx) { rpc_system_app_set_callback(subghz->rpc_ctx, NULL, NULL); + rpc_system_app_send_exited(subghz->rpc_ctx); + notification_message(subghz->notifications, &sequence_blink_stop); subghz->rpc_ctx = NULL; } @@ -322,24 +339,33 @@ int32_t subghz_app(void* p) { if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { subghz->rpc_ctx = (void*)rpc_ctx; rpc_system_app_set_callback(subghz->rpc_ctx, subghz_rpc_command_callback, subghz); + rpc_system_app_send_started(subghz->rpc_ctx); + view_dispatcher_attach_to_gui( + subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRpc); - } else if(subghz_key_load(subghz, p, true)) { - string_set_str(subghz->file_path, p); - - if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { - //Load Raw TX - subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); - } else { - //Load transmitter TX - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter); - } } else { - //exit app - scene_manager_stop(subghz->scene_manager); - view_dispatcher_stop(subghz->view_dispatcher); + view_dispatcher_attach_to_gui( + subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); + if(subghz_key_load(subghz, p, true)) { + string_set_str(subghz->file_path, p); + + if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { + //Load Raw TX + subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); + } else { + //Load transmitter TX + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter); + } + } else { + //exit app + scene_manager_stop(subghz->scene_manager); + view_dispatcher_stop(subghz->view_dispatcher); + } } } else { + view_dispatcher_attach_to_gui( + subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); if(load_database) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); diff --git a/assets/protobuf b/assets/protobuf index d9e34366..cc5918dc 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit d9e343661dd36cfab792b78be1dea4e5950cb4dd +Subproject commit cc5918dc488ac3617012ce5377114e086b447324