diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index d321439c5..749fe3a2f 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -134,6 +134,30 @@ static void subghz_scene_add_to_history_callback( if(subghz_history_get_text_space_left(subghz->history, NULL, 0)) { notification_message(subghz->notifications, &sequence_error); } + + if(subghz->ignore_duplicates) { + uint16_t history_count = subghz_history_get_last_index(subghz->history) - 1; + uint8_t hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); + uint16_t menu_idx = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver); + + for(uint16_t idx = history_count; idx > 0; idx--) { + if(subghz_history_get_hash_data(subghz->history, idx - 1) == hash_data) { + subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, idx - 1); + subghz_history_delete_item(subghz->history, idx - 1); + subghz_view_receiver_delete_element_callback(subghz->subghz_receiver); + if(menu_idx > idx - 1) menu_idx--; + } + } + + subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, menu_idx); + subghz->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz_view_receiver_enable_draw_callback(subghz->subghz_receiver); + subghz_scene_receiver_update_statusbar(subghz); + if(subghz_history_get_last_index(subghz->history) == 0) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart); + } + } } subghz_receiver_reset(receiver); furi_string_free(item_name); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 2d7f5014d..625fa2630 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -267,6 +267,15 @@ static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* it subghz->last_settings->rssi = raw_threshold_rssi_value[index]; } +static void subghz_scene_receiver_config_set_duplicates(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, combobox_text[index]); + + subghz->last_settings->ignore_duplicates = subghz->ignore_duplicates = index; +} + static inline bool subghz_scene_receiver_config_ignore_filter_get_index( SubGhzProtocolFilter filter, SubGhzProtocolFilter flag) { @@ -328,7 +337,9 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context, subghz_threshold_rssi_set(subghz->threshold_rssi, raw_threshold_rssi_value[default_index]); subghz->filter = bin_raw_value[0]; subghz->ignore_filter = 0x00; + subghz->ignore_duplicates = false; subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); + subghz->last_settings->ignore_duplicates = subghz->ignore_duplicates; subghz->last_settings->ignore_filter = subghz->ignore_filter; subghz->last_settings->filter = subghz->filter; @@ -419,6 +430,17 @@ void subghz_scene_receiver_config_on_enter(void* context) { if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerSet) { + item = variable_item_list_add( + subghz->variable_item_list, + "Ignore Duplicates", + COMBO_BOX_COUNT, + subghz_scene_receiver_config_set_duplicates, + subghz); + + value_index = subghz->ignore_duplicates; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, combobox_text[value_index]); + item = variable_item_list_add( subghz->variable_item_list, "Ignore Starline", diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 791c19684..bf835c83c 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -223,11 +223,13 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { subghz->secure_data = malloc(sizeof(SecureData)); if(!alloc_for_tx_only) { + subghz->ignore_duplicates = subghz->last_settings->ignore_duplicates; subghz->ignore_filter = subghz->last_settings->ignore_filter; subghz->filter = subghz->last_settings->filter; } else { subghz->filter = SubGhzProtocolFlag_Decodable; subghz->ignore_filter = 0x0; + subghz->ignore_duplicates = false; } subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); subghz_txrx_set_need_save_callback(subghz->txrx, subghz_save_to_file, subghz); diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index f50e14500..0812808c2 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -13,6 +13,7 @@ typedef struct { uint8_t type; SubGhzRadioPreset* preset; FuriHalRtcDateTime datetime; + uint8_t hash_data; float latitude; float longitude; } SubGhzHistoryItem; @@ -57,6 +58,12 @@ void subghz_history_free(SubGhzHistory* instance) { free(instance); } +uint8_t subghz_history_get_hash_data(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); + return item->hash_data; +} + uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); @@ -216,14 +223,14 @@ bool subghz_history_add_to_history( if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; SubGhzProtocolDecoderBase* decoder_base = context; - if((instance->code_last_hash_data == - subghz_protocol_decoder_base_get_hash_data(decoder_base)) && + uint8_t hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); + if((instance->code_last_hash_data == hash_data) && ((furi_get_tick() - instance->last_update_timestamp) < 500)) { instance->last_update_timestamp = furi_get_tick(); return false; } - instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); + instance->code_last_hash_data = hash_data; instance->last_update_timestamp = furi_get_tick(); FuriString* text = furi_string_alloc(); @@ -236,6 +243,7 @@ bool subghz_history_add_to_history( item->preset->data = preset->data; item->preset->data_size = preset->data_size; furi_hal_rtc_get_datetime(&item->datetime); + item->hash_data = hash_data; item->latitude = preset->latitude; item->longitude = preset->longitude; diff --git a/applications/main/subghz/subghz_history.h b/applications/main/subghz/subghz_history.h index 34d4cbd45..f2c93e127 100644 --- a/applications/main/subghz/subghz_history.h +++ b/applications/main/subghz/subghz_history.h @@ -29,6 +29,14 @@ void subghz_history_reset(SubGhzHistory* instance); void subghz_history_delete_item(SubGhzHistory* instance, uint16_t item_id); +/** Get hash data to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return hash - hash data byte + */ +uint8_t subghz_history_get_hash_data(SubGhzHistory* instance, uint16_t idx); + /** Get frequency to history[idx] * * @param instance - SubGhzHistory instance diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index 0cc5736a6..e032d3294 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -84,6 +84,7 @@ struct SubGhz { SubGhzProtocolFlag filter; SubGhzProtocolFilter ignore_filter; + bool ignore_duplicates; FuriString* error_str; SubGhzLock lock; diff --git a/applications/main/subghz/subghz_last_settings.c b/applications/main/subghz/subghz_last_settings.c index 675281742..35176c170 100644 --- a/applications/main/subghz/subghz_last_settings.c +++ b/applications/main/subghz/subghz_last_settings.c @@ -17,6 +17,7 @@ #define SUBGHZ_LAST_SETTING_FIELD_EXTERNAL_MODULE_POWER_AMP "ExtPowerAmp" #define SUBGHZ_LAST_SETTING_FIELD_GPS "Gps" #define SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE "Hopping" +#define SUBGHZ_LAST_SETTING_FIELD_IGNORE_DUPLICATES "IgnoreDuplicates" #define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter" #define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter" #define SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD "RSSI" @@ -45,6 +46,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count bool temp_external_module_power_amp = false; bool temp_timestamp_file_names = false; bool temp_enable_hopping = false; + bool temp_ignore_duplicates = false; uint32_t temp_ignore_filter = 0; uint32_t temp_filter = 0; float temp_rssi = 0; @@ -54,6 +56,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count bool rssi_was_read = false; bool filter_was_read = false; bool ignore_filter_was_read = false; + bool ignore_duplicates_was_read = false; bool frequency_analyzer_feedback_level_was_read = false; bool frequency_analyzer_trigger_was_read = false; uint32_t temp_gps_baudrate = 0; @@ -103,6 +106,11 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count 1); rssi_was_read = flipper_format_read_float( fff_data_file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, (float*)&temp_rssi, 1); + ignore_duplicates_was_read = flipper_format_read_bool( + fff_data_file, + SUBGHZ_LAST_SETTING_FIELD_IGNORE_DUPLICATES, + (bool*)&temp_ignore_duplicates, + 1); ignore_filter_was_read = flipper_format_read_uint32( fff_data_file, SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER, @@ -127,6 +135,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count instance->external_module_power_amp = false; instance->gps_baudrate = 0; instance->enable_hopping = false; + instance->ignore_duplicates = false; instance->ignore_filter = 0x00; // See bin_raw_value in applications/main/subghz/scenes/subghz_scene_receiver_config.c instance->filter = SubGhzProtocolFlag_Decodable; @@ -166,6 +175,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count instance->rssi = rssi_was_read ? temp_rssi : SUBGHZ_RAW_THRESHOLD_MIN; instance->enable_hopping = temp_enable_hopping; + instance->ignore_duplicates = ignore_duplicates_was_read ? temp_ignore_duplicates : false; instance->ignore_filter = ignore_filter_was_read ? temp_ignore_filter : 0x00; #if SUBGHZ_LAST_SETTING_SAVE_BIN_RAW instance->filter = filter_was_read ? temp_filter : SubGhzProtocolFlag_Decodable; @@ -273,6 +283,10 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, &instance->rssi, 1)) { break; } + if(!flipper_format_insert_or_update_bool( + file, SUBGHZ_LAST_SETTING_FIELD_IGNORE_DUPLICATES, &instance->ignore_duplicates, 1)) { + break; + } if(!flipper_format_insert_or_update_uint32( file, SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER, &instance->ignore_filter, 1)) { break; @@ -314,7 +328,7 @@ void subghz_last_settings_log(SubGhzLastSettings* instance) { TAG, "Frequency: %03ld.%02ld, FeedbackLevel: %ld, FATrigger: %.2f, External: %s, ExtPower: %s, TimestampNames: %s, ExtPowerAmp: %s,\n" "GPSBaudrate: %ld, Hopping: %s,\nPreset: %ld, RSSI: %.2f, " - "BinRAW: %s, Starline: %s, Cars: %s, Magellan: %s, NiceFloR-S: %s, Weather: %s, TPMS: %s", + "BinRAW: %s, Duplicates: %s, Starline: %s, Cars: %s, Magellan: %s, NiceFloR-S: %s, Weather: %s, TPMS: %s", instance->frequency / 1000000 % 1000, instance->frequency / 10000 % 100, instance->frequency_analyzer_feedback_level, @@ -328,6 +342,7 @@ void subghz_last_settings_log(SubGhzLastSettings* instance) { instance->preset_index, (double)instance->rssi, subghz_last_settings_log_filter_get_index(instance->filter, SubGhzProtocolFlag_BinRAW), + instance->ignore_duplicates ? LOG_ON : LOG_OFF, subghz_last_settings_log_filter_get_index( instance->ignore_filter, SubGhzProtocolFilter_StarLine), subghz_last_settings_log_filter_get_index( diff --git a/applications/main/subghz/subghz_last_settings.h b/applications/main/subghz/subghz_last_settings.h index c5a46946e..b91e2cd87 100644 --- a/applications/main/subghz/subghz_last_settings.h +++ b/applications/main/subghz/subghz_last_settings.h @@ -28,6 +28,7 @@ typedef struct { bool timestamp_file_names; uint32_t gps_baudrate; bool enable_hopping; + bool ignore_duplicates; uint32_t ignore_filter; uint32_t filter; float rssi;