Просмотр исходного кода

[FL-2610] SubGhz: add keypad lock SubGhz -> Read (#1343)

* [FL-2610] SubGhz: add keypad lock SubGhz -> Read
* SubGhz: fix multiple clicks on the back button
* SubGhz: turn on the backlight when receiving with the keypad locked. key processing delay when exiting Locked mode
* SubGhz: chanage lock variable and enums names
* SubGhz: replace direct return with consumed

Co-authored-by: あく <alleteam@gmail.com>
Skorpionm 3 лет назад
Родитель
Сommit
fea2bfa822

+ 3 - 0
applications/subghz/helpers/subghz_custom_event.h

@@ -41,6 +41,7 @@ typedef enum {
     SubGhzCustomEventSceneShowOnlyRX,
     SubGhzCustomEventSceneShowOnlyRX,
     SubGhzCustomEventSceneAnalyzerLock,
     SubGhzCustomEventSceneAnalyzerLock,
     SubGhzCustomEventSceneAnalyzerUnlock,
     SubGhzCustomEventSceneAnalyzerUnlock,
+    SubGhzCustomEventSceneSettingLock,
 
 
     SubGhzCustomEventSceneExit,
     SubGhzCustomEventSceneExit,
     SubGhzCustomEventSceneStay,
     SubGhzCustomEventSceneStay,
@@ -48,6 +49,8 @@ typedef enum {
     SubGhzCustomEventViewReceiverOK,
     SubGhzCustomEventViewReceiverOK,
     SubGhzCustomEventViewReceiverConfig,
     SubGhzCustomEventViewReceiverConfig,
     SubGhzCustomEventViewReceiverBack,
     SubGhzCustomEventViewReceiverBack,
+    SubGhzCustomEventViewReceiverOffDisplay,
+    SubGhzCustomEventViewReceiverUnlock,
 
 
     SubGhzCustomEventViewReadRAWBack,
     SubGhzCustomEventViewReadRAWBack,
     SubGhzCustomEventViewReadRAWIDLE,
     SubGhzCustomEventViewReadRAWIDLE,

+ 69 - 0
applications/subghz/helpers/subghz_types.h

@@ -0,0 +1,69 @@
+#pragma once
+
+/** SubGhzNotification state */
+typedef enum {
+    SubGhzNotificationStateStarting,
+    SubGhzNotificationStateIDLE,
+    SubGhzNotificationStateTx,
+    SubGhzNotificationStateRx,
+    SubGhzNotificationStateRxDone,
+} SubGhzNotificationState;
+
+/** SubGhzTxRx state */
+typedef enum {
+    SubGhzTxRxStateIDLE,
+    SubGhzTxRxStateRx,
+    SubGhzTxRxStateTx,
+    SubGhzTxRxStateSleep,
+} SubGhzTxRxState;
+
+/** SubGhzHopperState state */
+typedef enum {
+    SubGhzHopperStateOFF,
+    SubGhzHopperStateRunnig,
+    SubGhzHopperStatePause,
+    SubGhzHopperStateRSSITimeOut,
+} SubGhzHopperState;
+
+/** SubGhzRxKeyState state */
+typedef enum {
+    SubGhzRxKeyStateIDLE,
+    SubGhzRxKeyStateNoSave,
+    SubGhzRxKeyStateNeedSave,
+    SubGhzRxKeyStateBack,
+    SubGhzRxKeyStateStart,
+    SubGhzRxKeyStateAddKey,
+    SubGhzRxKeyStateExit,
+    SubGhzRxKeyStateRAWLoad,
+    SubGhzRxKeyStateRAWSave,
+} SubGhzRxKeyState;
+
+/** SubGhzLoadKeyState state */
+typedef enum {
+    SubGhzLoadKeyStateUnknown,
+    SubGhzLoadKeyStateOK,
+    SubGhzLoadKeyStateParseErr,
+    SubGhzLoadKeyStateOnlyRx,
+} SubGhzLoadKeyState;
+
+/** SubGhzLock */
+typedef enum {
+    SubGhzLockOff,
+    SubGhzLockOn,
+} SubGhzLock;
+
+typedef enum {
+    SubGhzViewIdMenu,
+    SubGhzViewIdReceiver,
+    SubGhzViewIdPopup,
+    SubGhzViewIdTextInput,
+    SubGhzViewIdWidget,
+    SubGhzViewIdTransmitter,
+    SubGhzViewIdVariableItemList,
+    SubGhzViewIdFrequencyAnalyzer,
+    SubGhzViewIdReadRAW,
+
+    SubGhzViewIdStatic,
+    SubGhzViewIdTestCarrier,
+    SubGhzViewIdTestPacket,
+} SubGhzViewId;

+ 12 - 11
applications/subghz/scenes/subghz_scene_read_raw.c

@@ -106,6 +106,7 @@ void subghz_scene_read_raw_on_enter(void* context) {
 
 
 bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
 bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
+    bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
         switch(event.event) {
         case SubGhzCustomEventViewReadRAWBack:
         case SubGhzCustomEventViewReadRAWBack:
@@ -141,7 +142,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                     }
                     }
                 }
                 }
             }
             }
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWTXRXStop:
         case SubGhzCustomEventViewReadRAWTXRXStop:
@@ -156,14 +157,14 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                 subghz_sleep(subghz);
                 subghz_sleep(subghz);
             };
             };
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->state_notifications = SubGhzNotificationStateIDLE;
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWConfig:
         case SubGhzCustomEventViewReadRAWConfig:
             scene_manager_set_scene_state(
             scene_manager_set_scene_state(
                 subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
                 subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWErase:
         case SubGhzCustomEventViewReadRAWErase:
@@ -175,7 +176,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
             }
             }
             subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
             subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
             notification_message(subghz->notifications, &sequence_reset_rgb);
             notification_message(subghz->notifications, &sequence_reset_rgb);
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWMore:
         case SubGhzCustomEventViewReadRAWMore:
@@ -184,7 +185,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                     subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
                     subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad;
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad;
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW);
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW);
-                return true;
+                consumed = true;
             } else {
             } else {
                 furi_crash("SubGhz: RAW file name update error.");
                 furi_crash("SubGhz: RAW file name update error.");
             }
             }
@@ -214,7 +215,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                     }
                     }
                 }
                 }
             }
             }
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWSendStop:
         case SubGhzCustomEventViewReadRAWSendStop:
@@ -224,7 +225,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                 subghz_sleep(subghz);
                 subghz_sleep(subghz);
             }
             }
             subghz_read_raw_stop_send(subghz->subghz_read_raw);
             subghz_read_raw_stop_send(subghz->subghz_read_raw);
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWIDLE:
         case SubGhzCustomEventViewReadRAWIDLE:
@@ -255,7 +256,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
             subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
 
 
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWREC:
         case SubGhzCustomEventViewReadRAWREC:
@@ -281,7 +282,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                     scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
                     scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
                 }
                 }
             }
             }
-            return true;
+            consumed = true;
             break;
             break;
 
 
         case SubGhzCustomEventViewReadRAWSave:
         case SubGhzCustomEventViewReadRAWSave:
@@ -291,7 +292,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
                 subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
             }
             }
-            return true;
+            consumed = true;
             break;
             break;
 
 
         default:
         default:
@@ -315,7 +316,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
             break;
             break;
         }
         }
     }
     }
-    return false;
+    return consumed;
 }
 }
 
 
 void subghz_scene_read_raw_on_exit(void* context) {
 void subghz_scene_read_raw_on_exit(void* context) {

+ 37 - 8
applications/subghz/scenes/subghz_scene_receiver.c

@@ -14,6 +14,23 @@ static const NotificationSequence subghs_sequence_rx = {
     NULL,
     NULL,
 };
 };
 
 
+static const NotificationSequence subghs_sequence_rx_locked = {
+    &message_green_255,
+
+    &message_display_backlight_on,
+
+    &message_vibro_on,
+    &message_note_c6,
+    &message_delay_50,
+    &message_sound_off,
+    &message_vibro_off,
+
+    &message_delay_500,
+
+    &message_display_backlight_off,
+    NULL,
+};
+
 static void subghz_scene_receiver_update_statusbar(void* context) {
 static void subghz_scene_receiver_update_statusbar(void* context) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
     string_t history_stat_str;
     string_t history_stat_str;
@@ -92,6 +109,8 @@ void subghz_scene_receiver_on_enter(void* context) {
         subghz->txrx->rx_key_state = SubGhzRxKeyStateStart;
         subghz->txrx->rx_key_state = SubGhzRxKeyStateStart;
     }
     }
 
 
+    subghz_view_receiver_set_lock(subghz->subghz_receiver, subghz->lock);
+
     //Load history to receiver
     //Load history to receiver
     subghz_view_receiver_exit(subghz->subghz_receiver);
     subghz_view_receiver_exit(subghz->subghz_receiver);
     for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) {
     for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) {
@@ -126,11 +145,10 @@ void subghz_scene_receiver_on_enter(void* context) {
 
 
 bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
 bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
-
+    bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
         switch(event.event) {
         case SubGhzCustomEventViewReceiverBack:
         case SubGhzCustomEventViewReceiverBack:
-
             // Stop CC1101 Rx
             // Stop CC1101 Rx
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
@@ -151,20 +169,28 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
                 scene_manager_search_and_switch_to_previous_scene(
                 scene_manager_search_and_switch_to_previous_scene(
                     subghz->scene_manager, SubGhzSceneStart);
                     subghz->scene_manager, SubGhzSceneStart);
             }
             }
-            return true;
+            consumed = true;
             break;
             break;
         case SubGhzCustomEventViewReceiverOK:
         case SubGhzCustomEventViewReceiverOK:
             subghz->txrx->idx_menu_chosen =
             subghz->txrx->idx_menu_chosen =
                 subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
                 subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
-            return true;
+            consumed = true;
             break;
             break;
         case SubGhzCustomEventViewReceiverConfig:
         case SubGhzCustomEventViewReceiverConfig:
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->state_notifications = SubGhzNotificationStateIDLE;
             subghz->txrx->idx_menu_chosen =
             subghz->txrx->idx_menu_chosen =
                 subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
                 subghz_view_receiver_get_idx_menu(subghz->subghz_receiver);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
-            return true;
+            consumed = true;
+            break;
+        case SubGhzCustomEventViewReceiverOffDisplay:
+            notification_message(subghz->notifications, &sequence_display_backlight_off);
+            consumed = true;
+            break;
+        case SubGhzCustomEventViewReceiverUnlock:
+            subghz->lock = SubGhzLockOff;
+            consumed = true;
             break;
             break;
         default:
         default:
             break;
             break;
@@ -174,20 +200,23 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
             subghz_hopper_update(subghz);
             subghz_hopper_update(subghz);
             subghz_scene_receiver_update_statusbar(subghz);
             subghz_scene_receiver_update_statusbar(subghz);
         }
         }
-
         switch(subghz->state_notifications) {
         switch(subghz->state_notifications) {
         case SubGhzNotificationStateRx:
         case SubGhzNotificationStateRx:
             notification_message(subghz->notifications, &sequence_blink_cyan_10);
             notification_message(subghz->notifications, &sequence_blink_cyan_10);
             break;
             break;
         case SubGhzNotificationStateRxDone:
         case SubGhzNotificationStateRxDone:
-            notification_message(subghz->notifications, &subghs_sequence_rx);
+            if(subghz->lock != SubGhzLockOn) {
+                notification_message(subghz->notifications, &subghs_sequence_rx);
+            } else {
+                notification_message(subghz->notifications, &subghs_sequence_rx_locked);
+            }
             subghz->state_notifications = SubGhzNotificationStateRx;
             subghz->state_notifications = SubGhzNotificationStateRx;
             break;
             break;
         default:
         default:
             break;
             break;
         }
         }
     }
     }
-    return false;
+    return consumed;
 }
 }
 
 
 void subghz_scene_receiver_on_exit(void* context) {
 void subghz_scene_receiver_on_exit(void* context) {

+ 35 - 3
applications/subghz/scenes/subghz_scene_receiver_config.c

@@ -1,5 +1,12 @@
 #include "../subghz_i.h"
 #include "../subghz_i.h"
 
 
+enum SubGhzSettingIndex {
+    SubGhzSettingIndexFrequency,
+    SubGhzSettingIndexHopping,
+    SubGhzSettingIndexModulation,
+    SubGhzSettingIndexLock,
+};
+
 #define PRESET_COUNT 4
 #define PRESET_COUNT 4
 const char* const preset_text[PRESET_COUNT] = {
 const char* const preset_text[PRESET_COUNT] = {
     "AM270",
     "AM270",
@@ -137,6 +144,15 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item)
     subghz->txrx->hopper_state = hopping_value[index];
     subghz->txrx->hopper_state = hopping_value[index];
 }
 }
 
 
+static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
+    furi_assert(context);
+    SubGhz* subghz = context;
+    if(index == SubGhzSettingIndexLock) {
+        view_dispatcher_send_custom_event(
+            subghz->view_dispatcher, SubGhzCustomEventSceneSettingLock);
+    }
+}
+
 void subghz_scene_receiver_config_on_enter(void* context) {
 void subghz_scene_receiver_config_on_enter(void* context) {
     SubGhz* subghz = context;
     SubGhz* subghz = context;
     VariableItem* item;
     VariableItem* item;
@@ -185,13 +201,29 @@ void subghz_scene_receiver_config_on_enter(void* context) {
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, preset_text[value_index]);
     variable_item_set_current_value_text(item, preset_text[value_index]);
 
 
+    if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
+       SubGhzCustomEventManagerSet) {
+        variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
+        variable_item_list_set_enter_callback(
+            subghz->variable_item_list,
+            subghz_scene_receiver_config_var_list_enter_callback,
+            subghz);
+    }
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
 }
 }
 
 
 bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent event) {
 bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
-    UNUSED(event);
-    return false;
+    SubGhz* subghz = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubGhzCustomEventSceneSettingLock) {
+            subghz->lock = SubGhzLockOn;
+            scene_manager_previous_scene(subghz->scene_manager);
+            consumed = true;
+        }
+    }
+    return consumed;
 }
 }
 
 
 void subghz_scene_receiver_config_on_exit(void* context) {
 void subghz_scene_receiver_config_on_exit(void* context) {

+ 2 - 1
applications/subghz/subghz.c

@@ -133,7 +133,8 @@ SubGhz* subghz_alloc() {
     subghz->setting = subghz_setting_alloc();
     subghz->setting = subghz_setting_alloc();
     subghz_setting_load(subghz->setting, "/ext/subghz/assets/setting_user");
     subghz_setting_load(subghz->setting, "/ext/subghz/assets/setting_user");
 
 
-    //init Worker & Protocol & History
+    //init Worker & Protocol & History & KeyBoard
+    subghz->lock = SubGhzLockOff;
     subghz->txrx = malloc(sizeof(SubGhzTxRx));
     subghz->txrx = malloc(sizeof(SubGhzTxRx));
     subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
     subghz->txrx->frequency = subghz_setting_get_default_frequency(subghz->setting);
     subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
     subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;

+ 2 - 62
applications/subghz/subghz_i.h

@@ -1,5 +1,6 @@
 #pragma once
 #pragma once
 
 
+#include "helpers/subghz_types.h"
 #include "subghz.h"
 #include "subghz.h"
 #include "views/receiver.h"
 #include "views/receiver.h"
 #include "views/transmitter.h"
 #include "views/transmitter.h"
@@ -37,52 +38,6 @@
 
 
 #define SUBGHZ_MAX_LEN_NAME 64
 #define SUBGHZ_MAX_LEN_NAME 64
 
 
-/** SubGhzNotification state */
-typedef enum {
-    SubGhzNotificationStateStarting,
-    SubGhzNotificationStateIDLE,
-    SubGhzNotificationStateTx,
-    SubGhzNotificationStateRx,
-    SubGhzNotificationStateRxDone,
-} SubGhzNotificationState;
-
-/** SubGhzTxRx state */
-typedef enum {
-    SubGhzTxRxStateIDLE,
-    SubGhzTxRxStateRx,
-    SubGhzTxRxStateTx,
-    SubGhzTxRxStateSleep,
-} SubGhzTxRxState;
-
-/** SubGhzHopperState state */
-typedef enum {
-    SubGhzHopperStateOFF,
-    SubGhzHopperStateRunnig,
-    SubGhzHopperStatePause,
-    SubGhzHopperStateRSSITimeOut,
-} SubGhzHopperState;
-
-/** SubGhzRxKeyState state */
-typedef enum {
-    SubGhzRxKeyStateIDLE,
-    SubGhzRxKeyStateNoSave,
-    SubGhzRxKeyStateNeedSave,
-    SubGhzRxKeyStateBack,
-    SubGhzRxKeyStateStart,
-    SubGhzRxKeyStateAddKey,
-    SubGhzRxKeyStateExit,
-    SubGhzRxKeyStateRAWLoad,
-    SubGhzRxKeyStateRAWSave,
-} SubGhzRxKeyState;
-
-/** SubGhzLoadKeyState state */
-typedef enum {
-    SubGhzLoadKeyStateUnknown,
-    SubGhzLoadKeyStateOK,
-    SubGhzLoadKeyStateParseErr,
-    SubGhzLoadKeyStateOnlyRx,
-} SubGhzLoadKeyState;
-
 struct SubGhzTxRx {
 struct SubGhzTxRx {
     SubGhzWorker* worker;
     SubGhzWorker* worker;
 
 
@@ -135,24 +90,9 @@ struct SubGhz {
     SubGhzTestPacket* subghz_test_packet;
     SubGhzTestPacket* subghz_test_packet;
     string_t error_str;
     string_t error_str;
     SubGhzSetting* setting;
     SubGhzSetting* setting;
+    SubGhzLock lock;
 };
 };
 
 
-typedef enum {
-    SubGhzViewIdMenu,
-    SubGhzViewIdReceiver,
-    SubGhzViewIdPopup,
-    SubGhzViewIdTextInput,
-    SubGhzViewIdWidget,
-    SubGhzViewIdTransmitter,
-    SubGhzViewIdVariableItemList,
-    SubGhzViewIdFrequencyAnalyzer,
-    SubGhzViewIdReadRAW,
-
-    SubGhzViewIdStatic,
-    SubGhzViewIdTestCarrier,
-    SubGhzViewIdTestPacket,
-} SubGhzViewId;
-
 bool subghz_set_preset(SubGhz* subghz, const char* preset);
 bool subghz_set_preset(SubGhz* subghz, const char* preset);
 void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation);
 void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_t modulation);
 void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);
 void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);

+ 124 - 12
applications/subghz/views/receiver.c

@@ -11,6 +11,7 @@
 #define FRAME_HEIGHT 12
 #define FRAME_HEIGHT 12
 #define MAX_LEN_PX 100
 #define MAX_LEN_PX 100
 #define MENU_ITEMS 4u
 #define MENU_ITEMS 4u
+#define UNLOCK_CNT 3
 
 
 typedef struct {
 typedef struct {
     string_t item_str;
     string_t item_str;
@@ -34,7 +35,17 @@ static const Icon* ReceiverItemIcons[] = {
     [SubGhzProtocolTypeDynamic] = &I_Lock_7x8,
     [SubGhzProtocolTypeDynamic] = &I_Lock_7x8,
 };
 };
 
 
+typedef enum {
+    SubGhzViewReceiverBarShowDefault,
+    SubGhzViewReceiverBarShowLock,
+    SubGhzViewReceiverBarShowToUnlockPress,
+    SubGhzViewReceiverBarShowUnlock,
+} SubGhzViewReceiverBarShow;
+
 struct SubGhzViewReceiver {
 struct SubGhzViewReceiver {
+    SubGhzLock lock;
+    uint8_t lock_count;
+    osTimerId_t timer;
     View* view;
     View* view;
     SubGhzViewReceiverCallback callback;
     SubGhzViewReceiverCallback callback;
     void* context;
     void* context;
@@ -48,8 +59,29 @@ typedef struct {
     uint16_t idx;
     uint16_t idx;
     uint16_t list_offset;
     uint16_t list_offset;
     uint16_t history_item;
     uint16_t history_item;
+    SubGhzViewReceiverBarShow bar_show;
 } SubGhzViewReceiverModel;
 } SubGhzViewReceiverModel;
 
 
+void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) {
+    furi_assert(subghz_receiver);
+    subghz_receiver->lock_count = 0;
+    if(lock == SubGhzLockOn) {
+        subghz_receiver->lock = lock;
+        with_view_model(
+            subghz_receiver->view, (SubGhzViewReceiverModel * model) {
+                model->bar_show = SubGhzViewReceiverBarShowLock;
+                return true;
+            });
+        osTimerStart(subghz_receiver->timer, pdMS_TO_TICKS(1000));
+    } else {
+        with_view_model(
+            subghz_receiver->view, (SubGhzViewReceiverModel * model) {
+                model->bar_show = SubGhzViewReceiverBarShowDefault;
+                return true;
+            });
+    }
+}
+
 void subghz_view_receiver_set_callback(
 void subghz_view_receiver_set_callback(
     SubGhzViewReceiver* subghz_receiver,
     SubGhzViewReceiver* subghz_receiver,
     SubGhzViewReceiverCallback callback,
     SubGhzViewReceiverCallback callback,
@@ -138,17 +170,6 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
 
 
     elements_button_left(canvas, "Config");
     elements_button_left(canvas, "Config");
-
-    canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str));
-    canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str));
-    canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str));
-    if(model->history_item == 0) {
-        canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str(canvas, 63, 46, "Scanning...");
-        canvas_draw_line(canvas, 46, 51, 125, 51);
-        return;
-    }
     canvas_draw_line(canvas, 46, 51, 125, 51);
     canvas_draw_line(canvas, 46, 51, 125, 51);
 
 
     bool scrollbar = model->history_item > 4;
     bool scrollbar = model->history_item > 4;
@@ -175,12 +196,96 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
         elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
         elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
     }
     }
     string_clear(str_buff);
     string_clear(str_buff);
+
+    canvas_set_color(canvas, ColorBlack);
+
+    if(model->history_item == 0) {
+        canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
+        canvas_set_font(canvas, FontPrimary);
+        canvas_draw_str(canvas, 63, 46, "Scanning...");
+        canvas_draw_line(canvas, 46, 51, 125, 51);
+        canvas_set_font(canvas, FontSecondary);
+    }
+
+    switch(model->bar_show) {
+    case SubGhzViewReceiverBarShowLock:
+        canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);
+        canvas_draw_str(canvas, 74, 62, "Locked");
+        break;
+    case SubGhzViewReceiverBarShowToUnlockPress:
+        canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str));
+        canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str));
+        canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str));
+        canvas_set_font(canvas, FontSecondary);
+        elements_bold_rounded_frame(canvas, 14, 8, 99, 48);
+        elements_multiline_text(canvas, 65, 26, "To unlock\npress:");
+        canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8);
+        canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8);
+        canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8);
+        canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
+        canvas_draw_dot(canvas, 17, 61);
+        break;
+    case SubGhzViewReceiverBarShowUnlock:
+        canvas_draw_icon(canvas, 64, 55, &I_Unlock_7x8);
+        canvas_draw_str(canvas, 74, 62, "Unlocked");
+        break;
+    default:
+        canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str));
+        canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str));
+        canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str));
+        break;
+    }
+}
+
+static void subghz_view_receiver_timer_callback(void* context) {
+    furi_assert(context);
+    SubGhzViewReceiver* subghz_receiver = context;
+    with_view_model(
+        subghz_receiver->view, (SubGhzViewReceiverModel * model) {
+            model->bar_show = SubGhzViewReceiverBarShowDefault;
+            return true;
+        });
+    if(subghz_receiver->lock_count < UNLOCK_CNT) {
+        subghz_receiver->callback(
+            SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context);
+    } else {
+        subghz_receiver->lock = SubGhzLockOff;
+        subghz_receiver->callback(SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context);
+    }
+    subghz_receiver->lock_count = 0;
 }
 }
 
 
 bool subghz_view_receiver_input(InputEvent* event, void* context) {
 bool subghz_view_receiver_input(InputEvent* event, void* context) {
     furi_assert(context);
     furi_assert(context);
     SubGhzViewReceiver* subghz_receiver = context;
     SubGhzViewReceiver* subghz_receiver = context;
 
 
+    if(subghz_receiver->lock == SubGhzLockOn) {
+        with_view_model(
+            subghz_receiver->view, (SubGhzViewReceiverModel * model) {
+                model->bar_show = SubGhzViewReceiverBarShowToUnlockPress;
+                return true;
+            });
+        if(subghz_receiver->lock_count == 0) {
+            osTimerStart(subghz_receiver->timer, pdMS_TO_TICKS(1000));
+        }
+        if(event->key == InputKeyBack && event->type == InputTypeShort) {
+            subghz_receiver->lock_count++;
+        }
+        if(subghz_receiver->lock_count >= UNLOCK_CNT) {
+            // subghz_receiver->callback(
+            //     SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context);
+            with_view_model(
+                subghz_receiver->view, (SubGhzViewReceiverModel * model) {
+                    model->bar_show = SubGhzViewReceiverBarShowUnlock;
+                    return true;
+                });
+            //subghz_receiver->lock = SubGhzLockOff;
+            osTimerStart(subghz_receiver->timer, pdMS_TO_TICKS(650));
+        }
+
+        return true;
+    }
+
     if(event->key == InputKeyBack && event->type == InputTypeShort) {
     if(event->key == InputKeyBack && event->type == InputTypeShort) {
         subghz_receiver->callback(SubGhzCustomEventViewReceiverBack, subghz_receiver->context);
         subghz_receiver->callback(SubGhzCustomEventViewReceiverBack, subghz_receiver->context);
     } else if(
     } else if(
@@ -240,6 +345,7 @@ void subghz_view_receiver_exit(void* context) {
                 model->history_item = 0;
                 model->history_item = 0;
                 return false;
                 return false;
         });
         });
+    osTimerStop(subghz_receiver->timer);
 }
 }
 
 
 SubGhzViewReceiver* subghz_view_receiver_alloc() {
 SubGhzViewReceiver* subghz_view_receiver_alloc() {
@@ -247,6 +353,9 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() {
 
 
     // View allocation and configuration
     // View allocation and configuration
     subghz_receiver->view = view_alloc();
     subghz_receiver->view = view_alloc();
+
+    subghz_receiver->lock = SubGhzLockOff;
+    subghz_receiver->lock_count = 0;
     view_allocate_model(
     view_allocate_model(
         subghz_receiver->view, ViewModelTypeLocking, sizeof(SubGhzViewReceiverModel));
         subghz_receiver->view, ViewModelTypeLocking, sizeof(SubGhzViewReceiverModel));
     view_set_context(subghz_receiver->view, subghz_receiver);
     view_set_context(subghz_receiver->view, subghz_receiver);
@@ -260,11 +369,13 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() {
             string_init(model->frequency_str);
             string_init(model->frequency_str);
             string_init(model->preset_str);
             string_init(model->preset_str);
             string_init(model->history_stat_str);
             string_init(model->history_stat_str);
+            model->bar_show = SubGhzViewReceiverBarShowDefault;
             model->history = malloc(sizeof(SubGhzReceiverHistory));
             model->history = malloc(sizeof(SubGhzReceiverHistory));
             SubGhzReceiverMenuItemArray_init(model->history->data);
             SubGhzReceiverMenuItemArray_init(model->history->data);
             return true;
             return true;
         });
         });
-
+    subghz_receiver->timer =
+        osTimerNew(subghz_view_receiver_timer_callback, osTimerOnce, subghz_receiver, NULL);
     return subghz_receiver;
     return subghz_receiver;
 }
 }
 
 
@@ -285,6 +396,7 @@ void subghz_view_receiver_free(SubGhzViewReceiver* subghz_receiver) {
                 free(model->history);
                 free(model->history);
                 return false;
                 return false;
         });
         });
+    osTimerDelete(subghz_receiver->timer);
     view_free(subghz_receiver->view);
     view_free(subghz_receiver->view);
     free(subghz_receiver);
     free(subghz_receiver);
 }
 }

+ 3 - 0
applications/subghz/views/receiver.h

@@ -1,12 +1,15 @@
 #pragma once
 #pragma once
 
 
 #include <gui/view.h>
 #include <gui/view.h>
+#include "../helpers/subghz_types.h"
 #include "../helpers/subghz_custom_event.h"
 #include "../helpers/subghz_custom_event.h"
 
 
 typedef struct SubGhzViewReceiver SubGhzViewReceiver;
 typedef struct SubGhzViewReceiver SubGhzViewReceiver;
 
 
 typedef void (*SubGhzViewReceiverCallback)(SubGhzCustomEvent event, void* context);
 typedef void (*SubGhzViewReceiverCallback)(SubGhzCustomEvent event, void* context);
 
 
+void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard);
+
 void subghz_view_receiver_set_callback(
 void subghz_view_receiver_set_callback(
     SubGhzViewReceiver* subghz_receiver,
     SubGhzViewReceiver* subghz_receiver,
     SubGhzViewReceiverCallback callback,
     SubGhzViewReceiverCallback callback,