better subghz settings and more anim unload fixes

by Willy-JL
This commit is contained in:
MX 2024-04-05 06:36:35 +03:00
parent a830d6b511
commit ef29ed149d
No known key found for this signature in database
GPG key ID: 7CCC66B7DBDD1C83
15 changed files with 167 additions and 241 deletions

View file

@ -60,9 +60,6 @@ bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent e
subghz_frequency_analyzer_get_frequency_to_save(subghz->subghz_frequency_analyzer); subghz_frequency_analyzer_get_frequency_to_save(subghz->subghz_frequency_analyzer);
if(frequency > 0) { if(frequency > 0) {
subghz->last_settings->frequency = frequency; subghz->last_settings->frequency = frequency;
#ifdef FURI_DEBUG
subghz_last_settings_log(subghz->last_settings);
#endif
// Disable Hopping before opening the receiver scene! // Disable Hopping before opening the receiver scene!
if(subghz->last_settings->enable_hopping) { if(subghz->last_settings->enable_hopping) {
subghz->last_settings->enable_hopping = false; subghz->last_settings->enable_hopping = false;
@ -73,9 +70,6 @@ bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent e
return true; return true;
} else if(event.event == SubGhzCustomEventViewFreqAnalOkLong) { } else if(event.event == SubGhzCustomEventViewFreqAnalOkLong) {
// Don't need to save, we already saved on short event // Don't need to save, we already saved on short event
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Goto next scene!");
#endif
//scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneStart, 10); //scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneStart, 10);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
return true; return true;

View file

@ -94,7 +94,7 @@ static void subghz_scene_receiver_config_set_timestamp_file_names(VariableItem*
variable_item_set_current_value_text(item, timestamp_names_text[index]); variable_item_set_current_value_text(item, timestamp_names_text[index]);
subghz->last_settings->timestamp_file_names = (index == 1); subghz->last_settings->protocol_file_names = (index == 1);
subghz_last_settings_save(subghz->last_settings); subghz_last_settings_save(subghz->last_settings);
} }
@ -126,7 +126,7 @@ void subghz_scene_radio_settings_on_enter(void* context) {
TIMESTAMP_NAMES_COUNT, TIMESTAMP_NAMES_COUNT,
subghz_scene_receiver_config_set_timestamp_file_names, subghz_scene_receiver_config_set_timestamp_file_names,
subghz); subghz);
value_index = subghz->last_settings->timestamp_file_names; value_index = subghz->last_settings->protocol_file_names;
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, timestamp_names_text[value_index]); variable_item_set_current_value_text(item, timestamp_names_text[value_index]);

View file

@ -104,14 +104,13 @@ void subghz_scene_read_raw_on_enter(void* context) {
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) { if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
#if SUBGHZ_LAST_SETTING_SAVE_PRESET
if(furi_string_empty(file_name)) { if(furi_string_empty(file_name)) {
subghz_txrx_set_preset_internal( subghz_txrx_set_preset_internal(
subghz->txrx, subghz->txrx,
subghz->last_settings->frequency, subghz->last_settings->frequency,
subghz->last_settings->preset_index); subghz->last_settings->preset_index);
} }
#endif
} }
subghz_scene_read_raw_update_statusbar(subghz); subghz_scene_read_raw_update_statusbar(subghz);

View file

@ -164,12 +164,8 @@ void subghz_scene_receiver_on_enter(void* context) {
FuriString* item_time = furi_string_alloc(); FuriString* item_time = furi_string_alloc();
if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateIDLE) { if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateIDLE) {
#if SUBGHZ_LAST_SETTING_SAVE_PRESET
subghz_txrx_set_preset_internal( subghz_txrx_set_preset_internal(
subghz->txrx, subghz->last_settings->frequency, subghz->last_settings->preset_index); subghz->txrx, subghz->last_settings->frequency, subghz->last_settings->preset_index);
#else
subghz_txrx_set_default_preset(subghz->txrx, subghz->last_settings->frequency);
#endif
subghz->filter = subghz->last_settings->filter; subghz->filter = subghz->last_settings->filter;
subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter);

View file

@ -301,14 +301,11 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context,
subghz->view_dispatcher, SubGhzCustomEventSceneSettingLock); subghz->view_dispatcher, SubGhzCustomEventSceneSettingLock);
} else if(index == SubGhzSettingIndexResetToDefault) { } else if(index == SubGhzSettingIndexResetToDefault) {
// Reset all values to default state! // Reset all values to default state!
#if SUBGHZ_LAST_SETTING_SAVE_PRESET
subghz_txrx_set_preset_internal( subghz_txrx_set_preset_internal(
subghz->txrx, subghz->txrx,
SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY, SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY,
SUBGHZ_LAST_SETTING_DEFAULT_PRESET); SUBGHZ_LAST_SETTING_DEFAULT_PRESET);
#else
subghz_txrx_set_default_preset(subghz->txrx, SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY);
#endif
SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx);
SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx);
const char* preset_name = furi_string_get_cstr(preset.name); const char* preset_name = furi_string_get_cstr(preset.name);
@ -333,9 +330,7 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context,
variable_item_list_set_selected_item(subghz->variable_item_list, default_index); variable_item_list_set_selected_item(subghz->variable_item_list, default_index);
variable_item_list_reset(subghz->variable_item_list); variable_item_list_reset(subghz->variable_item_list);
#ifdef FURI_DEBUG
subghz_last_settings_log(subghz->last_settings);
#endif
subghz_last_settings_save(subghz->last_settings); subghz_last_settings_save(subghz->last_settings);
view_dispatcher_send_custom_event( view_dispatcher_send_custom_event(
@ -556,9 +551,7 @@ void subghz_scene_receiver_config_on_exit(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
variable_item_list_set_selected_item(subghz->variable_item_list, 0); variable_item_list_set_selected_item(subghz->variable_item_list, 0);
variable_item_list_reset(subghz->variable_item_list); variable_item_list_reset(subghz->variable_item_list);
#ifdef FURI_DEBUG
subghz_last_settings_log(subghz->last_settings);
#endif
subghz_last_settings_save(subghz->last_settings); subghz_last_settings_save(subghz->last_settings);
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet);

View file

@ -32,7 +32,7 @@ void subghz_scene_save_name_on_enter(void* context) {
if(decoder_result != 0x0) { if(decoder_result != 0x0) {
if(decoder_result != NULL) { if(decoder_result != NULL) {
if(strlen(decoder_result->protocol->name) != 0 && if(strlen(decoder_result->protocol->name) != 0 &&
subghz->last_settings->timestamp_file_names) { subghz->last_settings->protocol_file_names) {
if(!scene_manager_has_previous_scene( if(!scene_manager_has_previous_scene(
subghz->scene_manager, SubGhzSceneSetType)) { subghz->scene_manager, SubGhzSceneSetType)) {
name_generator_make_auto_datetime( name_generator_make_auto_datetime(

View file

@ -202,16 +202,9 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->last_settings = subghz_last_settings_alloc(); subghz->last_settings = subghz_last_settings_alloc();
size_t preset_count = subghz_setting_get_preset_count(setting); size_t preset_count = subghz_setting_get_preset_count(setting);
subghz_last_settings_load(subghz->last_settings, preset_count); subghz_last_settings_load(subghz->last_settings, preset_count);
#ifdef FURI_DEBUG
subghz_last_settings_log(subghz->last_settings);
#endif
if(!alloc_for_tx_only) { if(!alloc_for_tx_only) {
#if SUBGHZ_LAST_SETTING_SAVE_PRESET
subghz_txrx_set_preset_internal( subghz_txrx_set_preset_internal(
subghz->txrx, subghz->last_settings->frequency, subghz->last_settings->preset_index); subghz->txrx, subghz->last_settings->frequency, subghz->last_settings->preset_index);
#else
subghz_txrx_set_default_preset(subghz->txrx, subghz->last_settings->frequency);
#endif
subghz->history = subghz_history_alloc(); subghz->history = subghz_history_alloc();
} }

View file

@ -4,14 +4,14 @@
#define TAG "SubGhzLastSettings" #define TAG "SubGhzLastSettings"
#define SUBGHZ_LAST_SETTING_FILE_TYPE "Flipper SubGhz Last Setting File" #define SUBGHZ_LAST_SETTING_FILE_TYPE "Flipper SubGhz Last Setting File"
#define SUBGHZ_LAST_SETTING_FILE_VERSION 2 #define SUBGHZ_LAST_SETTING_FILE_VERSION 3
#define SUBGHZ_LAST_SETTINGS_PATH EXT_PATH("subghz/assets/last_subghz.settings") #define SUBGHZ_LAST_SETTINGS_PATH EXT_PATH("subghz/assets/last_subghz.settings")
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency" #define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency"
#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset" // AKA Modulation #define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset" // AKA Modulation
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL "FeedbackLevel" #define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL "FeedbackLevel"
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER "FATrigger" #define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER "FATrigger"
#define SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES "TimestampNames" #define SUBGHZ_LAST_SETTING_FIELD_PROTOCOL_FILE_NAMES "ProtocolNames"
#define SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE "Hopping" #define SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE "Hopping"
#define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter" #define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter"
#define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter" #define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter"
@ -31,31 +31,23 @@ void subghz_last_settings_free(SubGhzLastSettings* instance) {
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count) { void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count) {
furi_assert(instance); furi_assert(instance);
// Default values (all others set to 0, if read from file fails these are used)
instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY;
instance->preset_index = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
instance->frequency_analyzer_feedback_level =
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
// See bin_raw_value in scenes/subghz_scene_receiver_config.c
instance->filter = SubGhzProtocolFlag_Decodable;
instance->rssi = SUBGHZ_RAW_THRESHOLD_MIN;
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
uint32_t temp_frequency = 0;
uint32_t temp_frequency_analyzer_feedback_level = 0;
float temp_frequency_analyzer_trigger = 0;
bool temp_timestamp_file_names = false;
bool temp_enable_hopping = false;
bool temp_delete_old_sig = false;
uint32_t temp_ignore_filter = 0;
uint32_t temp_filter = 0;
float temp_rssi = 0;
uint32_t temp_preset = 0;
bool preset_was_read = false;
bool rssi_was_read = false;
bool filter_was_read = false;
bool ignore_filter_was_read = false;
bool frequency_analyzer_feedback_level_was_read = false;
bool frequency_analyzer_trigger_was_read = false;
FuriString* temp_str = furi_string_alloc(); FuriString* temp_str = furi_string_alloc();
uint32_t config_version = 0; uint32_t config_version = 0;
if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH && if(FSE_OK == storage_sd_status(storage) &&
flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) { flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) {
do { do {
if(!flipper_format_read_header(fff_data_file, temp_str, &config_version)) break; if(!flipper_format_read_header(fff_data_file, temp_str, &config_version)) break;
@ -64,44 +56,65 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
break; break;
} }
preset_was_read = flipper_format_read_uint32( if(!flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_PRESET, (uint32_t*)&temp_preset, 1); fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) {
flipper_format_read_uint32( flipper_format_rewind(fff_data_file);
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, (uint32_t*)&temp_frequency, 1); }
frequency_analyzer_feedback_level_was_read = flipper_format_read_uint32( if(!flipper_format_read_uint32(
fff_data_file, fff_data_file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset_index, 1)) {
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL, flipper_format_rewind(fff_data_file);
(uint32_t*)&temp_frequency_analyzer_feedback_level, }
1); if(!flipper_format_read_uint32(
frequency_analyzer_trigger_was_read = flipper_format_read_float( fff_data_file,
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL,
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER, &instance->frequency_analyzer_feedback_level,
(float*)&temp_frequency_analyzer_trigger, 1)) {
1); flipper_format_rewind(fff_data_file);
flipper_format_read_bool( }
fff_data_file, if(!flipper_format_read_float(
SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES, fff_data_file,
(bool*)&temp_timestamp_file_names, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER,
1); &instance->frequency_analyzer_trigger,
flipper_format_read_bool( 1)) {
fff_data_file, flipper_format_rewind(fff_data_file);
SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE, }
(bool*)&temp_enable_hopping, if(!flipper_format_read_bool(
1); fff_data_file,
rssi_was_read = flipper_format_read_float( SUBGHZ_LAST_SETTING_FIELD_PROTOCOL_FILE_NAMES,
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, (float*)&temp_rssi, 1); &instance->protocol_file_names,
ignore_filter_was_read = flipper_format_read_uint32( 1)) {
fff_data_file, flipper_format_rewind(fff_data_file);
SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER, }
(uint32_t*)&temp_ignore_filter, if(!flipper_format_read_bool(
1); fff_data_file,
filter_was_read = flipper_format_read_uint32( SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE,
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FILTER, (uint32_t*)&temp_filter, 1); &instance->enable_hopping,
flipper_format_read_bool( 1)) {
fff_data_file, flipper_format_rewind(fff_data_file);
SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD, }
(bool*)&temp_delete_old_sig, if(!flipper_format_read_uint32(
1); fff_data_file,
SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER,
&instance->ignore_filter,
1)) {
flipper_format_rewind(fff_data_file);
}
if(!flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) {
flipper_format_rewind(fff_data_file);
}
if(!flipper_format_read_float(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, &instance->rssi, 1)) {
flipper_format_rewind(fff_data_file);
}
if(!flipper_format_read_bool(
fff_data_file,
SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD,
&instance->delete_old_signals,
1)) {
flipper_format_rewind(fff_data_file);
}
} while(0); } while(0);
} else { } else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH); FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
@ -109,76 +122,22 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
furi_string_free(temp_str); furi_string_free(temp_str);
if(temp_frequency == 0 || !furi_hal_subghz_is_tx_allowed(temp_frequency)) {
FURI_LOG_W(TAG, "Last used frequency not found or can't be used!");
instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY;
instance->preset_index = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
instance->frequency_analyzer_feedback_level =
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
instance->timestamp_file_names = false;
instance->enable_hopping = false;
instance->delete_old_signals = false;
instance->ignore_filter = 0x00;
// See bin_raw_value in applications/main/subghz/scenes/subghz_scene_receiver_config.c
instance->filter = SubGhzProtocolFlag_Decodable;
instance->rssi = SUBGHZ_RAW_THRESHOLD_MIN;
} else {
instance->frequency = temp_frequency;
instance->frequency_analyzer_feedback_level =
frequency_analyzer_feedback_level_was_read ?
temp_frequency_analyzer_feedback_level :
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = frequency_analyzer_trigger_was_read ?
temp_frequency_analyzer_trigger :
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
if(!preset_was_read) {
FURI_LOG_W(TAG, "Preset was not read. Set default");
instance->preset_index = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
} else if(temp_preset > (uint32_t)preset_count - 1) {
FURI_LOG_W(
TAG,
"Last used preset out of range. Preset to set: %ld, Max index: %ld. Set default",
temp_preset,
(uint32_t)preset_count - 1);
instance->preset_index = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
} else {
instance->preset_index = temp_preset;
}
instance->timestamp_file_names = temp_timestamp_file_names;
instance->delete_old_signals = temp_delete_old_sig;
instance->rssi = rssi_was_read ? temp_rssi : SUBGHZ_RAW_THRESHOLD_MIN;
instance->enable_hopping = temp_enable_hopping;
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;
#else
if(filter_was_read) {
instance->filter = temp_filter != SubGhzProtocolFlag_Decodable ?
SubGhzProtocolFlag_Decodable :
temp_filter;
} else {
instance->filter = SubGhzProtocolFlag_Decodable;
}
#endif
}
flipper_format_file_close(fff_data_file); flipper_format_file_close(fff_data_file);
flipper_format_free(fff_data_file); flipper_format_free(fff_data_file);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
if(instance->frequency == 0 || !furi_hal_subghz_is_tx_allowed(instance->frequency)) {
instance->frequency = SUBGHZ_LAST_SETTING_DEFAULT_FREQUENCY;
}
if(instance->preset_index > (uint32_t)preset_count - 1) {
instance->preset_index = SUBGHZ_LAST_SETTING_DEFAULT_PRESET;
}
} }
bool subghz_last_settings_save(SubGhzLastSettings* instance) { bool subghz_last_settings_save(SubGhzLastSettings* instance) {
furi_assert(instance); furi_assert(instance);
#if SUBGHZ_LAST_SETTING_SAVE_BIN_RAW != true
instance->filter = SubGhzProtocolFlag_Decodable;
#endif
bool saved = false; bool saved = false;
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* file = flipper_format_file_alloc(storage); FlipperFormat* file = flipper_format_file_alloc(storage);
@ -195,55 +154,56 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
if(!flipper_format_write_header_cstr( if(!flipper_format_write_header_cstr(
file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION)) file, SUBGHZ_LAST_SETTING_FILE_TYPE, SUBGHZ_LAST_SETTING_FILE_VERSION))
break; break;
if(!flipper_format_insert_or_update_uint32( if(!flipper_format_write_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset_index, 1)) {
break;
}
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) { file, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY, &instance->frequency, 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_uint32( if(!flipper_format_write_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_PRESET, &instance->preset_index, 1)) {
break;
}
if(!flipper_format_write_uint32(
file, file,
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL,
&instance->frequency_analyzer_feedback_level, &instance->frequency_analyzer_feedback_level,
1)) { 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_float( if(!flipper_format_write_float(
file, file,
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER, SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER,
&instance->frequency_analyzer_trigger, &instance->frequency_analyzer_trigger,
1)) { 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_bool( if(!flipper_format_write_bool(
file, file,
SUBGHZ_LAST_SETTING_FIELD_TIMESTAMP_FILE_NAMES, SUBGHZ_LAST_SETTING_FIELD_PROTOCOL_FILE_NAMES,
&instance->timestamp_file_names, &instance->protocol_file_names,
1)) { 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_bool( if(!flipper_format_write_bool(
file, SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE, &instance->enable_hopping, 1)) { file, SUBGHZ_LAST_SETTING_FIELD_HOPPING_ENABLE, &instance->enable_hopping, 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_float( if(!flipper_format_write_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, &instance->rssi, 1)) {
break;
}
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER, &instance->ignore_filter, 1)) { file, SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER, &instance->ignore_filter, 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_uint32( if(!flipper_format_write_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) { file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) {
break; break;
} }
if(!flipper_format_insert_or_update_bool( if(!flipper_format_write_float(
file, SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD, &instance->rssi, 1)) {
break;
}
if(!flipper_format_write_bool(
file, SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD, &instance->delete_old_signals, 1)) { file, SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD, &instance->delete_old_signals, 1)) {
break; break;
} }
saved = true; saved = true;
} while(0); } while(0);
@ -257,42 +217,3 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
return saved; return saved;
} }
const char* LOG_ON = "ON";
const char* LOG_OFF = "OFF";
static inline const char*
subghz_last_settings_log_filter_get_index(uint32_t filter, uint32_t flag) {
return READ_BIT(filter, flag) > 0 ? LOG_ON : LOG_OFF;
}
static inline const char* bool_to_char(bool value) {
return value ? LOG_ON : LOG_OFF;
}
void subghz_last_settings_log(SubGhzLastSettings* instance) {
furi_assert(instance);
FURI_LOG_I(
TAG,
"Frequency: %03ld.%02ld, FeedbackLevel: %ld, FATrigger: %.2f, TimestampNames: %s,\n"
"Hopping: %s,\nPreset: %ld, RSSI: %.2f, "
"Starline: %s, Cars: %s, Magellan: %s, NiceFloR-S: %s, BinRAW: %s",
instance->frequency / 1000000 % 1000,
instance->frequency / 10000 % 100,
instance->frequency_analyzer_feedback_level,
(double)instance->frequency_analyzer_trigger,
bool_to_char(instance->timestamp_file_names),
bool_to_char(instance->enable_hopping),
instance->preset_index,
(double)instance->rssi,
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFlag_StarLine),
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFlag_AutoAlarms),
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFlag_Magellan),
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFlag_NiceFlorS),
subghz_last_settings_log_filter_get_index(instance->filter, SubGhzProtocolFlag_BinRAW));
}

View file

@ -7,8 +7,6 @@
#include <lib/subghz/types.h> #include <lib/subghz/types.h>
#define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER (-93.0f) #define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER (-93.0f)
#define SUBGHZ_LAST_SETTING_SAVE_BIN_RAW true
#define SUBGHZ_LAST_SETTING_SAVE_PRESET true
// 1 = "AM650" // 1 = "AM650"
// "AM270", "AM650", "FM238", "FM476", // "AM270", "AM650", "FM238", "FM476",
#define SUBGHZ_LAST_SETTING_DEFAULT_PRESET 1 #define SUBGHZ_LAST_SETTING_DEFAULT_PRESET 1
@ -20,7 +18,7 @@ typedef struct {
uint32_t preset_index; // AKA Modulation uint32_t preset_index; // AKA Modulation
uint32_t frequency_analyzer_feedback_level; uint32_t frequency_analyzer_feedback_level;
float frequency_analyzer_trigger; float frequency_analyzer_trigger;
bool timestamp_file_names; bool protocol_file_names;
bool enable_hopping; bool enable_hopping;
uint32_t ignore_filter; uint32_t ignore_filter;
uint32_t filter; uint32_t filter;
@ -35,5 +33,3 @@ void subghz_last_settings_free(SubGhzLastSettings* instance);
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count); void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count);
bool subghz_last_settings_save(SubGhzLastSettings* instance); bool subghz_last_settings_save(SubGhzLastSettings* instance);
void subghz_last_settings_log(SubGhzLastSettings* instance);

View file

@ -32,12 +32,14 @@ static void desktop_loader_callback(const void* message, void* context) {
Desktop* desktop = context; Desktop* desktop = context;
const LoaderEvent* event = message; const LoaderEvent* event = message;
if(event->type == LoaderEventTypeApplicationStarted) { if(event->type == LoaderEventTypeApplicationBeforeLoad) {
desktop->animation_lock = api_lock_alloc_locked(); desktop->animation_lock = api_lock_alloc_locked();
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted); view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted);
api_lock_wait_unlock_and_free(desktop->animation_lock); api_lock_wait_unlock_and_free(desktop->animation_lock);
desktop->animation_lock = NULL; desktop->animation_lock = NULL;
} else if(event->type == LoaderEventTypeApplicationStopped) { } else if(
event->type == LoaderEventTypeApplicationLoadFailed ||
event->type == LoaderEventTypeApplicationStopped) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished);
} }
} }

View file

@ -152,7 +152,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
break; break;
case DesktopMainEventOpenPowerOff: { case DesktopMainEventOpenPowerOff: {
loader_start(desktop->loader, "Power", "off", NULL); loader_start_detached_with_gui_error(desktop->loader, "Power", "off");
consumed = true; consumed = true;
break; break;
} }

View file

@ -47,34 +47,16 @@ LoaderStatus
return result.value; return result.value;
} }
LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { static void loader_show_gui_error(LoaderStatus status, FuriString* error_message) {
furi_check(loader); // TODO FL-3522: we have many places where we can emit a double start, ex: desktop, menu
furi_check(name); // so i prefer to not show LoaderStatusErrorAppStarted error message for now
if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) {
FuriString* error_message = furi_string_alloc();
LoaderStatus status = loader_start(loader, name, args, error_message);
if(status == LoaderStatusErrorUnknownApp &&
loader_find_external_application_by_name(name) != NULL) {
// Special case for external apps
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Update needed", 64, 3, AlignCenter, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, NULL);
dialog_message_set_icon(message, &I_WarningDolphinFlip_45x42, 83, 22);
dialog_message_set_text(
message, "Update firmware\nto run this app", 3, 26, AlignLeft, AlignTop);
dialog_message_show(dialogs, message);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} else if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) {
// TODO FL-3522: we have many places where we can emit a double start, ex: desktop, menu
// so i prefer to not show LoaderStatusErrorAppStarted error message for now
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc(); DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, NULL); dialog_message_set_buttons(message, NULL, NULL, NULL);
furi_string_replace(error_message, ":", "\n");
furi_string_replace(error_message, "/ext/apps/", ""); furi_string_replace(error_message, "/ext/apps/", "");
furi_string_replace(error_message, ", ", "\n"); furi_string_replace(error_message, ", ", "\n");
furi_string_replace(error_message, ": ", "\n"); furi_string_replace(error_message, ": ", "\n");
@ -86,11 +68,31 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const
dialog_message_free(message); dialog_message_free(message);
furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_DIALOGS);
} }
}
LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) {
furi_check(loader);
furi_check(name);
FuriString* error_message = furi_string_alloc();
LoaderStatus status = loader_start(loader, name, args, error_message);
loader_show_gui_error(status, error_message);
furi_string_free(error_message); furi_string_free(error_message);
return status; return status;
} }
void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args) {
furi_check(loader);
furi_check(name);
LoaderMessage message;
message.type = LoaderMessageTypeStartByNameDetachedWithGuiError;
message.start.name = name ? strdup(name) : NULL;
message.start.args = args ? strdup(args) : NULL;
furi_message_queue_put(loader->queue, &message, FuriWaitForever);
}
bool loader_lock(Loader* loader) { bool loader_lock(Loader* loader) {
furi_check(loader); furi_check(loader);
@ -256,6 +258,9 @@ static void loader_start_internal_app(
const FlipperInternalApplication* app, const FlipperInternalApplication* app,
const char* args) { const char* args) {
FURI_LOG_I(TAG, "Starting %s", app->name); FURI_LOG_I(TAG, "Starting %s", app->name);
LoaderEvent event;
event.type = LoaderEventTypeApplicationBeforeLoad;
furi_pubsub_publish(loader->pubsub, &event);
// store args // store args
furi_assert(loader->app.args == NULL); furi_assert(loader->app.args == NULL);
@ -311,6 +316,9 @@ static LoaderStatus loader_start_external_app(
FuriString* error_message, FuriString* error_message,
bool ignore_mismatch) { bool ignore_mismatch) {
LoaderStatus status = loader_make_success_status(error_message); LoaderStatus status = loader_make_success_status(error_message);
LoaderEvent event;
event.type = LoaderEventTypeApplicationBeforeLoad;
furi_pubsub_publish(loader->pubsub, &event);
do { do {
loader->app.fap = flipper_application_alloc(storage, firmware_api_interface); loader->app.fap = flipper_application_alloc(storage, firmware_api_interface);
@ -390,6 +398,8 @@ static LoaderStatus loader_start_external_app(
if(status != LoaderStatusOk) { if(status != LoaderStatusOk) {
flipper_application_free(loader->app.fap); flipper_application_free(loader->app.fap);
loader->app.fap = NULL; loader->app.fap = NULL;
event.type = LoaderEventTypeApplicationLoadFailed;
furi_pubsub_publish(loader->pubsub, &event);
} }
return status; return status;
@ -567,6 +577,16 @@ int32_t loader_srv(void* p) {
loader, message.start.name, message.start.args, message.start.error_message); loader, message.start.name, message.start.args, message.start.error_message);
api_lock_unlock(message.api_lock); api_lock_unlock(message.api_lock);
break; break;
case LoaderMessageTypeStartByNameDetachedWithGuiError: {
FuriString* error_message = furi_string_alloc();
LoaderStatus status = loader_do_start_by_name(
loader, message.start.name, message.start.args, error_message);
loader_show_gui_error(status, error_message);
if(message.start.name) free((void*)message.start.name);
if(message.start.args) free((void*)message.start.args);
furi_string_free(error_message);
break;
}
case LoaderMessageTypeShowMenu: case LoaderMessageTypeShowMenu:
loader_do_menu_show(loader); loader_do_menu_show(loader);
break; break;

View file

@ -20,6 +20,8 @@ typedef enum {
} LoaderStatus; } LoaderStatus;
typedef enum { typedef enum {
LoaderEventTypeApplicationBeforeLoad,
LoaderEventTypeApplicationLoadFailed,
LoaderEventTypeApplicationStarted, LoaderEventTypeApplicationStarted,
LoaderEventTypeApplicationStopped LoaderEventTypeApplicationStopped
} LoaderEventType; } LoaderEventType;
@ -48,6 +50,14 @@ LoaderStatus
*/ */
LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args); LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args);
/**
* @brief Start application detached with GUI error message
* @param[in] instance loader instance
* @param[in] name application name
* @param[in] args application arguments
*/
void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args);
/** /**
* @brief Lock application start * @brief Lock application start
* @param[in] instance loader instance * @param[in] instance loader instance

View file

@ -30,6 +30,7 @@ typedef enum {
LoaderMessageTypeLock, LoaderMessageTypeLock,
LoaderMessageTypeUnlock, LoaderMessageTypeUnlock,
LoaderMessageTypeIsLocked, LoaderMessageTypeIsLocked,
LoaderMessageTypeStartByNameDetachedWithGuiError,
} LoaderMessageType; } LoaderMessageType;
typedef struct { typedef struct {

View file

@ -2172,6 +2172,7 @@ Function,+,loader_is_locked,_Bool,Loader*
Function,+,loader_lock,_Bool,Loader* Function,+,loader_lock,_Bool,Loader*
Function,+,loader_show_menu,void,Loader* Function,+,loader_show_menu,void,Loader*
Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*, FuriString*" Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*, FuriString*"
Function,+,loader_start_detached_with_gui_error,void,"Loader*, const char*, const char*"
Function,+,loader_start_with_gui_error,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_start_with_gui_error,LoaderStatus,"Loader*, const char*, const char*"
Function,+,loader_unlock,void,Loader* Function,+,loader_unlock,void,Loader*
Function,+,loading_alloc,Loading*, Function,+,loading_alloc,Loading*,

1 entry status name type params
2172 Function + loader_lock _Bool Loader*
2173 Function + loader_show_menu void Loader*
2174 Function + loader_start LoaderStatus Loader*, const char*, const char*, FuriString*
2175 Function + loader_start_detached_with_gui_error void Loader*, const char*, const char*
2176 Function + loader_start_with_gui_error LoaderStatus Loader*, const char*, const char*
2177 Function + loader_unlock void Loader*
2178 Function + loading_alloc Loading*