SubGHZ Repeater, Enable Sound Saved to Last Settings. (#492) --nobuild

This commit is contained in:
WillyJL
2023-12-14 03:21:25 +00:00
committed by GitHub
15 changed files with 403 additions and 121 deletions

View File

@@ -82,6 +82,7 @@ typedef enum {
SubGhzCustomEventSceneShowOnlyRX,
SubGhzCustomEventSceneAnalyzerLock,
SubGhzCustomEventSceneAnalyzerUnlock,
SubGhzCustomEventSceneSettingRepeater,
SubGhzCustomEventSceneSettingRemoveDuplicates,
SubGhzCustomEventSceneSettingLock,
SubGhzCustomEventSceneSettingResetToDefault,
@@ -95,6 +96,8 @@ typedef enum {
SubGhzCustomEventSceneRpcSessionClose,
SubGhzCustomEventViewReceiverOK,
SubGhzCustomEventViewReceiverOKLong,
SubGhzCustomEventViewReceiverOKRelease,
SubGhzCustomEventViewReceiverConfig,
SubGhzCustomEventViewReceiverBack,
SubGhzCustomEventViewReceiverOffDisplay,
@@ -120,5 +123,8 @@ typedef enum {
SubGhzCustomEventViewFreqAnalOkShort,
SubGhzCustomEventViewFreqAnalOkLong,
SubGhzCustomEventViewRepeaterStart,
SubGhzCustomEventViewRepeaterStop,
SubGhzCustomEventByteInputDone,
} SubGhzCustomEvent;

View File

@@ -53,6 +53,7 @@ typedef enum {
SubGhzRxKeyStateExit,
SubGhzRxKeyStateRAWLoad,
SubGhzRxKeyStateRAWSave,
SubGhzRxKeyStateTX,
} SubGhzRxKeyState;
/** SubGhzLoadKeyState state */
@@ -101,4 +102,12 @@ typedef enum {
SubGhzDecodeRawStateStart,
SubGhzDecodeRawStateLoading,
SubGhzDecodeRawStateLoaded,
} SubGhzDecodeRawState;
} SubGhzDecodeRawState;
/** SubGhz Repeater */
typedef enum {
SubGhzRepeaterStateOff,
SubGhzRepeaterStateOn,
SubGhzRepeaterStateOnLong,
SubGhzRepeaterStateOnShort,
} SubGhzRepeaterState;

View File

@@ -20,7 +20,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
furi_string_get_cstr(modulation_str),
furi_string_get_cstr(history_stat_str),
subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF,
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0);
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0,
subghz->repeater);
furi_string_free(frequency_str);
furi_string_free(modulation_str);
@@ -31,7 +32,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
"",
"",
subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF,
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0);
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0,
subghz->repeater);
}
furi_string_free(history_stat_str);
}

View File

@@ -16,7 +16,7 @@ void subghz_scene_need_saving_on_enter(void* context) {
SubGhz* subghz = context;
widget_add_string_multiline_element(
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Sub-GHz Menu?");
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Discard Signals?");
widget_add_string_multiline_element(
subghz->widget,
64,
@@ -29,7 +29,7 @@ void subghz_scene_need_saving_on_enter(void* context) {
widget_add_button_element(
subghz->widget, GuiButtonTypeRight, "Stay", subghz_scene_need_saving_callback, subghz);
widget_add_button_element(
subghz->widget, GuiButtonTypeLeft, "Exit", subghz_scene_need_saving_callback, subghz);
subghz->widget, GuiButtonTypeLeft, "Continue", subghz_scene_need_saving_callback, subghz);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
}
@@ -54,6 +54,15 @@ bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
subghz->txrx, "AM650", subghz->last_settings->frequency, 0, 0, NULL, 0);
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);
} else if(state == SubGhzRxKeyStateTX) {
subghz->repeater = SubGhzRepeaterStateOn;
subghz->last_settings->repeater_state = SubGhzRepeaterStateOn;
if((subghz->filter & SubGhzProtocolFlag_BinRAW) == 0) {
subghz->filter = SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW;
subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter);
subghz->repeater_bin_raw_was_off = true;
}
scene_manager_previous_scene(subghz->scene_manager);
} else {
scene_manager_previous_scene(subghz->scene_manager);
}

View File

@@ -130,15 +130,6 @@ void subghz_scene_read_raw_on_enter(void* context) {
if(subghz->fav_timeout) {
scene_manager_handle_custom_event(
subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart);
// with_view_model(
// subghz->subghz_read_raw->view,
// SubGhzReadRAWModel * model,
// {
// scene_manager_handle_custom_event(
// subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart);
// model->status = SubGhzReadRAWStatusTXRepeat;
// },
// true);
}
}

View File

@@ -36,6 +36,16 @@ const NotificationSequence subghz_sequence_rx_locked = {
NULL,
};
const NotificationSequence subghz_sequence_tx_beep = {
&message_vibro_on,
&message_note_c6,
&message_delay_50,
&message_sound_off,
&message_vibro_off,
&message_delay_50,
NULL,
};
static void subghz_scene_receiver_update_statusbar(void* context) {
SubGhz* subghz = context;
FuriString* history_stat_str = furi_string_alloc();
@@ -72,7 +82,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
furi_string_get_cstr(modulation_str),
furi_string_get_cstr(history_stat_str),
subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF,
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0);
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0,
subghz->repeater);
furi_string_free(frequency_str);
furi_string_free(modulation_str);
@@ -83,7 +94,8 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
"",
"",
subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF,
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0);
READ_BIT(subghz->filter, SubGhzProtocolFlag_BinRAW) > 0,
subghz->repeater);
subghz->state_notifications = SubGhzNotificationStateIDLE;
}
furi_string_free(history_stat_str);
@@ -98,6 +110,11 @@ void subghz_scene_receiver_callback(SubGhzCustomEvent event, void* context) {
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
}
void repeater_stop_callback(void* context) {
SubGhz* subghz = context;
scene_manager_handle_custom_event(subghz->scene_manager, SubGhzCustomEventViewRepeaterStop);
}
static void subghz_scene_add_to_history_callback(
SubGhzReceiver* receiver,
SubGhzProtocolDecoderBase* decoder_base,
@@ -120,50 +137,57 @@ static void subghz_scene_add_to_history_callback(
furi_string_reset(item_name);
furi_string_reset(item_time);
subghz->state_notifications = SubGhzNotificationStateRxDone;
//If the repeater is on, dont add to the menu, just TX the signal.
if(subghz->repeater != SubGhzRepeaterStateOff) {
//subghz_scene_receiver_update_statusbar(subghz);
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewRepeaterStart);
} else {
subghz->state_notifications = SubGhzNotificationStateRxDone;
if(subghz->remove_duplicates) {
// Look in history for signal hash
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 i = idx; i > 0; i--) {
i--; // Iterating in reverse with off by one
if(subghz_history_get_hash_data(subghz->history, i) == hash_data) {
// Remove previous instance and update menu index
subghz_history_delete_item(subghz->history, i);
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, i);
subghz_view_receiver_delete_element_callback(subghz->subghz_receiver);
if(menu_idx > i) {
menu_idx--;
idx--;
if(subghz->remove_duplicates) {
// Look in history for signal hash
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 i = idx; i > 0; i--) {
i--; // Iterating in reverse with off by one
if(subghz_history_get_hash_data(subghz->history, i) == hash_data) {
// Remove previous instance and update menu index
subghz_history_delete_item(subghz->history, i);
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, i);
subghz_view_receiver_delete_element_callback(subghz->subghz_receiver);
if(menu_idx > i) {
menu_idx--;
idx--;
}
}
i++;
}
// Restore ui state
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);
if(subghz_history_get_last_index(subghz->history) == 0) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart);
}
i++;
}
// Restore ui state
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);
if(subghz_history_get_last_index(subghz->history) == 0) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart);
subghz_history_get_text_item_menu(history, item_name, idx);
subghz_history_get_time_item_menu(history, item_time, idx);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(history, idx),
subghz_history_get_repeats(history, idx));
subghz_scene_receiver_update_statusbar(subghz);
if(subghz_history_get_text_space_left(subghz->history, NULL, 0)) {
notification_message(subghz->notifications, &sequence_error);
}
}
subghz_history_get_text_item_menu(history, item_name, idx);
subghz_history_get_time_item_menu(history, item_time, idx);
subghz_view_receiver_add_item_to_menu(
subghz->subghz_receiver,
furi_string_get_cstr(item_name),
furi_string_get_cstr(item_time),
subghz_history_get_type_protocol(history, idx),
subghz_history_get_repeats(history, idx));
subghz_scene_receiver_update_statusbar(subghz);
if(subghz_history_get_text_space_left(subghz->history, NULL, 0)) {
notification_message(subghz->notifications, &sequence_error);
}
}
subghz_receiver_reset(receiver);
furi_string_free(item_name);
@@ -233,6 +257,32 @@ void subghz_scene_receiver_on_enter(void* context) {
subghz_txrx_hopper_set_state(subghz->txrx, SubGhzHopperStateOFF);
}
// Check if Sound was enabled, and restart the Speaker.
subghz_txrx_speaker_set_state(
subghz->txrx,
subghz->last_settings->enable_sound ? SubGhzSpeakerStateEnable :
SubGhzSpeakerStateShutdown);
//Set up a timer for the repeater (recycled favorites timeout TX timer!).
if(!subghz->timer)
subghz->timer = furi_timer_alloc(repeater_stop_callback, FuriTimerTypeOnce, subghz);
//Remember if the repeater was loaded, and do cleanups we need.
subghz->repeater = subghz->last_settings->repeater_state;
//Did the user set BinRAW or me?
if(subghz->repeater != SubGhzRepeaterStateOff) {
//User had BinRAW on if the last settings had BinRAW on, if not, repeater is on, and BinRAW goes on, but State CHanged is false!
subghz->repeater_bin_raw_was_off =
(subghz->last_settings->filter & SubGhzProtocolFlag_BinRAW) == 0;
if((subghz->filter & SubGhzProtocolFlag_BinRAW) == 0) {
subghz->filter = SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW;
subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter);
}
} else {
subghz->repeater_bin_raw_was_off = false;
}
subghz_txrx_rx_start(subghz->txrx);
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->idx_menu_chosen);
@@ -309,35 +359,104 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_unlock(subghz);
consumed = true;
break;
case SubGhzCustomEventViewRepeaterStart:
subghz_txrx_stop(subghz->txrx);
subghz_txrx_hopper_pause(subghz->txrx);
FlipperFormat* key_repeat_data = subghz_history_get_raw_data(
subghz->history, subghz_history_get_last_index(subghz->history) - 1);
uint32_t tmpTe = 300;
if(!flipper_format_rewind(key_repeat_data)) {
FURI_LOG_E(TAG, "Rewind error");
} else if(!flipper_format_read_uint32(key_repeat_data, "TE", (uint32_t*)&tmpTe, 1)) {
FURI_LOG_E(TAG, "Missing TE");
}
if(!subghz_tx_start(subghz, key_repeat_data)) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewRepeaterStop);
} else {
subghz->state_notifications = SubGhzNotificationStateTx;
notification_message(subghz->notifications, &subghz_sequence_tx_beep);
uint32_t repeatnormal = (tmpTe > 1000) ? 1 : 3;
uint32_t repeat_time = ((subghz->repeater & SubGhzRepeaterStateOnLong) != 0) ?
2 * repeatnormal * tmpTe :
((subghz->repeater & SubGhzRepeaterStateOnShort) != 0) ?
1 * tmpTe :
repeatnormal * tmpTe;
furi_timer_start(subghz->timer, repeat_time);
}
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateTX);
break;
case SubGhzCustomEventViewRepeaterStop:
subghz_txrx_stop(subghz->txrx);
subghz_history_delete_item(
subghz->history, subghz_history_get_last_index(subghz->history) - 1);
subghz_txrx_rx_start(subghz->txrx);
subghz_txrx_hopper_unpause(subghz->txrx);
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart);
subghz->state_notifications = SubGhzNotificationStateRx;
break;
case SubGhzCustomEventViewReceiverOKLong:
subghz_txrx_stop(subghz->txrx);
subghz_txrx_hopper_pause(subghz->txrx);
if(!subghz_tx_start(
subghz,
subghz_history_get_raw_data(
subghz->history,
subghz_view_receiver_get_idx_menu(subghz->subghz_receiver)))) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewReceiverOKRelease);
} else {
subghz->state_notifications = SubGhzNotificationStateTx;
notification_message(subghz->notifications, &subghz_sequence_tx_beep);
}
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateTX);
break;
case SubGhzCustomEventViewReceiverOKRelease:
if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateTX) {
subghz_txrx_stop(subghz->txrx);
subghz_txrx_rx_start(subghz->txrx);
subghz_txrx_hopper_unpause(subghz->txrx);
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart);
subghz->state_notifications = SubGhzNotificationStateRx;
break;
}
break;
default:
break;
}
} else if(event.type == SceneManagerEventTypeTick) {
if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) {
subghz_txrx_hopper_update(subghz->txrx);
subghz_scene_receiver_update_statusbar(subghz);
}
SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(
subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx));
if(subghz->last_settings->gps_baudrate != 0) {
FuriHalRtcDateTime datetime;
furi_hal_rtc_get_datetime(&datetime);
if((datetime.second - subghz->gps->fix_second) > 15) {
subghz->gps->latitude = NAN;
subghz->gps->longitude = NAN;
subghz->gps->satellites = 0;
subghz->gps->fix_hour = 0;
subghz->gps->fix_minute = 0;
subghz->gps->fix_second = 0;
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateTX) {
if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) {
subghz_txrx_hopper_update(subghz->txrx);
subghz_scene_receiver_update_statusbar(subghz);
}
subghz_scene_receiver_update_statusbar(subghz);
}
subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi);
subghz_protocol_decoder_bin_raw_data_input_rssi(
(SubGhzProtocolDecoderBinRAW*)subghz_txrx_get_decoder(subghz->txrx), ret_rssi.rssi);
SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(
subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx));
if(subghz->last_settings->gps_baudrate != 0) {
FuriHalRtcDateTime datetime;
furi_hal_rtc_get_datetime(&datetime);
if((datetime.second - subghz->gps->fix_second) > 15) {
subghz->gps->latitude = NAN;
subghz->gps->longitude = NAN;
subghz->gps->satellites = 0;
subghz->gps->fix_hour = 0;
subghz->gps->fix_minute = 0;
subghz->gps->fix_second = 0;
}
subghz_scene_receiver_update_statusbar(subghz);
}
subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi);
subghz_protocol_decoder_bin_raw_data_input_rssi(
(SubGhzProtocolDecoderBinRAW*)subghz_txrx_get_decoder(subghz->txrx),
ret_rssi.rssi);
}
switch(subghz->state_notifications) {
case SubGhzNotificationStateRx:
@@ -359,6 +478,9 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
}
subghz->state_notifications = SubGhzNotificationStateRx;
break;
case SubGhzNotificationStateTx:
notification_message(subghz->notifications, &sequence_blink_magenta_10);
break;
default:
break;
}

View File

@@ -10,6 +10,7 @@ enum SubGhzSettingIndex {
SubGhzSettingIndexRAWSound = SubGhzSettingIndexHopping,
SubGhzSettingIndexBinRAW,
SubGhzSettingIndexRAWRSSIThreshold = SubGhzSettingIndexBinRAW,
SubGhzSettingIndexRepeater,
SubGhzSettingIndexRemoveDuplicates,
SubGhzSettingIndexIgnoreStarline,
SubGhzSettingIndexIgnoreCars,
@@ -74,6 +75,20 @@ const char* const combobox_text[COMBO_BOX_COUNT] = {
"ON",
};
#define REPEATER_COUNT 4
const char* const repeater_text[REPEATER_COUNT] = {
"OFF",
"Normal",
"Long",
"Short",
};
const uint32_t repeater_value[REPEATER_COUNT] = {
SubGhzRepeaterStateOff,
SubGhzRepeaterStateOn,
SubGhzRepeaterStateOnLong,
SubGhzRepeaterStateOnShort,
};
static void subghz_scene_receiver_config_set_ignore_filter(
VariableItem* item,
SubGhzProtocolFilter filter) {
@@ -133,8 +148,7 @@ SubGhzHopperState subghz_scene_receiver_config_hopper_value_index(void* context)
return SubGhzHopperStateOFF;
} else {
variable_item_set_current_value_text(
(VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig),
variable_item_list_get(subghz->variable_item_list, SubGhzSettingIndexFrequency),
" -----");
return SubGhzHopperStateRunning;
}
@@ -200,8 +214,8 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
SubGhz* subghz = variable_item_get_context(item);
SubGhzHopperState index = variable_item_get_current_value_index(item);
SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx);
VariableItem* frequency_item = (VariableItem*)scene_manager_get_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig);
VariableItem* frequency_item =
variable_item_list_get(subghz->variable_item_list, SubGhzSettingIndexFrequency);
variable_item_set_current_value_text(item, combobox_text[(uint8_t)index]);
@@ -244,6 +258,7 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) {
variable_item_set_current_value_text(item, combobox_text[index]);
subghz_txrx_speaker_set_state(subghz->txrx, speaker_value[index]);
subghz->last_settings->enable_sound = (speaker_value[index] == SubGhzSpeakerStateEnable);
}
static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) {
@@ -256,6 +271,59 @@ static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) {
// We can set here, but during subghz_last_settings_save filter was changed to ignore BinRAW
subghz->last_settings->filter = subghz->filter;
//If the user changed BinRAW menu, dont reset it with the repeater.
subghz->repeater_bin_raw_was_off = false;
}
static void subghz_scene_receiver_config_set_repeater(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
if(subghz->repeater == SubGhzRepeaterStateOff &&
(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey ||
subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateBack)) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig, SubGhzSettingIndexRepeater);
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventSceneSettingRepeater);
return;
}
//Set menu Text.
variable_item_set_current_value_text(item, repeater_text[index]);
//Save state and in last settings.
subghz->repeater = repeater_value[index];
subghz->last_settings->repeater_state = repeater_value[index];
//Get the BinRAW menu for state change.
VariableItem* bin_raw_menu =
variable_item_list_get(subghz->variable_item_list, SubGhzSettingIndexBinRAW);
//Change BinRAW to ON or OFF as required, and remember whether I changed it! (Put back for the user.)
if(repeater_value[index] != SubGhzRepeaterStateOff) {
if((subghz->filter & SubGhzProtocolFlag_BinRAW) == 0) {
//Repeater is on, Binraw is Off.
variable_item_set_current_value_index(
bin_raw_menu, 1 /*Index of ON in BIN_Raw menu!*/);
subghz_scene_receiver_config_set_bin_raw(bin_raw_menu);
subghz->repeater_bin_raw_was_off = true;
}
//Lock the BinRAW menu, Flipper doesnt understand everything so BinRAW makes every key send.
variable_item_set_locked(bin_raw_menu, true, NULL);
} else {
//Put BinRAW back how it was, if we changed it.
if(subghz->repeater_bin_raw_was_off) {
variable_item_set_current_value_index(
bin_raw_menu, 0 /*Index of OFF in BIN_Raw menu!*/);
subghz_scene_receiver_config_set_bin_raw(bin_raw_menu);
}
//Lock the BinRAW menu, Flipper doesnt understand everything so BinRAW makes very key send.
variable_item_set_locked(bin_raw_menu, false, NULL);
}
}
static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) {
@@ -347,8 +415,11 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context,
subghz->last_settings->remove_duplicates = subghz->remove_duplicates;
subghz->last_settings->ignore_filter = subghz->ignore_filter;
subghz->last_settings->filter = subghz->filter;
subghz->last_settings->repeater_state = SubGhzRepeaterStateOff;
subghz->repeater = SubGhzRepeaterStateOff;
subghz_txrx_speaker_set_state(subghz->txrx, speaker_value[default_index]);
subghz->last_settings->enable_sound = false;
subghz_txrx_hopper_set_state(subghz->txrx, hopping_value[default_index]);
subghz->last_settings->enable_hopping = hopping_value[default_index];
@@ -379,8 +450,6 @@ void subghz_scene_receiver_config_on_enter(void* context) {
subghz_scene_receiver_config_set_frequency,
subghz);
value_index = subghz_scene_receiver_config_next_frequency(preset.frequency, subghz);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item);
variable_item_set_current_value_index(item, value_index);
char text_buf[10] = {0};
uint32_t frequency = subghz_setting_get_frequency(setting, value_index);
@@ -431,10 +500,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
value_index = value_index_uint32(subghz->filter, bin_raw_value, COMBO_BOX_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, combobox_text[value_index]);
}
variable_item_set_locked(
item, subghz->repeater != SubGhzRepeaterStateOff, "Turn off\nRepeater\nto do that!");
item = variable_item_list_add(
subghz->variable_item_list,
"Repeater",
REPEATER_COUNT,
subghz_scene_receiver_config_set_repeater,
subghz);
value_index = value_index_uint32(subghz->repeater, repeater_value, REPEATER_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, repeater_text[value_index]);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
item = variable_item_list_add(
subghz->variable_item_list,
"Remove Duplicates",
@@ -578,6 +657,12 @@ void subghz_scene_receiver_config_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, raw_threshold_rssi_text[value_index]);
}
variable_item_list_set_selected_item(
subghz->variable_item_list,
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReceiverConfig));
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneReceiverConfig, 0);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
}
@@ -586,7 +671,11 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventSceneSettingRemoveDuplicates) {
if(event.event == SubGhzCustomEventSceneSettingRepeater) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateTX);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
consumed = true;
} else if(event.event == SubGhzCustomEventSceneSettingRemoveDuplicates) {
subghz_history_remove_duplicates(subghz->history);
scene_manager_previous_scene(subghz->scene_manager);
consumed = true;
@@ -604,6 +693,11 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even
void subghz_scene_receiver_config_on_exit(void* context) {
SubGhz* subghz = context;
if(subghz->repeater_bin_raw_was_off) {
subghz->last_settings->filter = bin_raw_value[0 /*BinRAW Off*/];
}
variable_item_list_set_selected_item(subghz->variable_item_list, 0);
variable_item_list_reset(subghz->variable_item_list);
#ifdef FURI_DEBUG

View File

@@ -70,19 +70,12 @@ void subghz_scene_transmitter_on_enter(void* context) {
// Auto send and exit with favorites
if(subghz->fav_timeout) {
// subghz_custom_btn_set(0);
furi_check(!subghz->timer, "SubGhz fav timer exists");
subghz->timer = furi_timer_alloc(fav_timer_callback, FuriTimerTypeOnce, subghz);
scene_manager_handle_custom_event(
subghz->scene_manager, SubGhzCustomEventViewTransmitterSendStart);
// with_view_model(
// subghz->subghz_transmitter->view,
// SubGhzViewTransmitterModel * model,
// { model->show_button = false; },
// true);
subghz->fav_timer = furi_timer_alloc(fav_timer_callback, FuriTimerTypeOnce, subghz);
furi_timer_start(
subghz->fav_timer,
xtreme_settings.favorite_timeout * furi_kernel_get_tick_frequency());
// subghz->state_notifications = SubGhzNotificationStateTx;
subghz->timer, xtreme_settings.favorite_timeout * furi_kernel_get_tick_frequency());
}
}

View File

@@ -429,9 +429,9 @@ int32_t subghz_app(char* p) {
view_dispatcher_run(subghz->view_dispatcher);
if(subghz->fav_timer) {
furi_timer_stop(subghz->fav_timer);
furi_timer_free(subghz->fav_timer);
if(subghz->timer) {
furi_timer_stop(subghz->timer);
furi_timer_free(subghz->timer);
}
furi_hal_power_suppress_charge_exit();

View File

@@ -96,12 +96,14 @@ struct SubGhz {
SubGhzRxKeyState rx_key_state;
SubGhzHistory* history;
SubGhzGPS* gps;
SubGhzRepeaterState repeater;
bool repeater_bin_raw_was_off;
uint16_t idx_menu_chosen;
SubGhzLoadTypeFile load_type_file;
bool fav_timeout;
FuriTimer* fav_timer;
FuriTimer* timer;
void* rpc_ctx;
};

View File

@@ -21,6 +21,8 @@
#define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter"
#define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter"
#define SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD "RSSI"
#define SUBGHZ_LAST_SETTING_FIELD_REPEATER "Repeater"
#define SUBGHZ_LAST_SETTING_FIELD_ENABLE_SOUND "Sound"
SubGhzLastSettings* subghz_last_settings_alloc(void) {
SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings));
@@ -46,6 +48,8 @@ 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_enable_sound = false;
uint32_t temp_repeater_state;
bool temp_remove_duplicates = false;
uint32_t temp_ignore_filter = 0;
uint32_t temp_filter = 0;
@@ -59,6 +63,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
bool remove_duplicates_was_read = false;
bool frequency_analyzer_feedback_level_was_read = false;
bool frequency_analyzer_trigger_was_read = false;
bool repeater_was_read = false;
bool enable_sound_was_read = false;
uint32_t temp_gps_baudrate = 0;
if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH &&
@@ -118,6 +125,11 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
1);
filter_was_read = flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FILTER, (uint32_t*)&temp_filter, 1);
repeater_was_read = flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_REPEATER, (uint32_t*)&temp_repeater_state, 1);
enable_sound_was_read = flipper_format_read_bool(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_ENABLE_SOUND, (bool*)&temp_enable_sound, 1);
} else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
}
@@ -136,6 +148,8 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->gps_baudrate = 0;
instance->enable_hopping = false;
instance->remove_duplicates = false;
instance->repeater_state = 0;
instance->enable_sound = 0;
instance->ignore_filter = 0x00;
// See bin_raw_value in applications/main/subghz/scenes/subghz_scene_receiver_config.c
instance->filter = SubGhzProtocolFlag_Decodable;
@@ -175,6 +189,8 @@ 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->repeater_state = repeater_was_read ? temp_repeater_state : 0;
instance->enable_sound = enable_sound_was_read ? temp_enable_sound : false;
instance->remove_duplicates = remove_duplicates_was_read ? temp_remove_duplicates : false;
instance->ignore_filter = ignore_filter_was_read ? temp_ignore_filter : 0x00;
#if SUBGHZ_LAST_SETTING_SAVE_BIN_RAW
@@ -298,6 +314,14 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) {
break;
}
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_REPEATER, &instance->repeater_state, 1)) {
break;
}
if(!flipper_format_insert_or_update_bool(
file, SUBGHZ_LAST_SETTING_FIELD_ENABLE_SOUND, &instance->enable_sound, 1)) {
break;
}
saved = true;
} while(0);
@@ -331,7 +355,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, Duplicates: %s, Starline: %s, Cars: %s, Magellan: %s, NiceFloR-S: %s, Weather: %s, TPMS: %s",
"BinRAW: %s, Repeater: %lu, Duplicates: %s, Starline: %s, Cars: %s, Magellan: %s, NiceFloR-S: %s, Weather: %s, TPMS: %s, Sound: %s",
instance->frequency / 1000000 % 1000,
instance->frequency / 10000 % 100,
instance->frequency_analyzer_feedback_level,
@@ -345,7 +369,8 @@ 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->remove_duplicates ? LOG_ON : LOG_OFF,
instance->repeater_state,
bool_to_char(instance->remove_duplicates),
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFilter_StarLine),
subghz_last_settings_log_filter_get_index(
@@ -357,5 +382,6 @@ void subghz_last_settings_log(SubGhzLastSettings* instance) {
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFilter_Weather),
subghz_last_settings_log_filter_get_index(
instance->ignore_filter, SubGhzProtocolFilter_TPMS));
instance->ignore_filter, SubGhzProtocolFilter_TPMS),
bool_to_char(instance->enable_sound));
}

View File

@@ -28,6 +28,8 @@ typedef struct {
bool timestamp_file_names;
uint32_t gps_baudrate;
bool enable_hopping;
uint32_t repeater_state;
bool enable_sound;
bool remove_duplicates;
uint32_t ignore_filter;
uint32_t filter;

View File

@@ -65,6 +65,7 @@ typedef struct {
FuriString* progress_str;
bool hopping_enabled;
bool bin_raw_enabled;
SubGhzRepeaterState repeater_state;
SubGhzReceiverHistory* history;
uint16_t idx;
uint16_t list_offset;
@@ -207,7 +208,8 @@ void subghz_view_receiver_add_data_statusbar(
const char* preset_str,
const char* history_stat_str,
bool hopping_enabled,
bool bin_raw_enabled) {
bool bin_raw_enabled,
SubGhzRepeaterState repeater_state) {
furi_assert(subghz_receiver);
with_view_model(
subghz_receiver->view,
@@ -218,6 +220,7 @@ void subghz_view_receiver_add_data_statusbar(
furi_string_set(model->history_stat_str, history_stat_str);
model->hopping_enabled = hopping_enabled;
model->bin_raw_enabled = bin_raw_enabled;
model->repeater_state = repeater_state;
},
true);
}
@@ -336,7 +339,9 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
(model->device_type == SubGhzRadioDeviceTypeInternal) ? &I_Scanning_123x52 :
&I_Fishing_123x52);
canvas_set_font(canvas, FontPrimary);
if(model->hopping_enabled) {
if(model->repeater_state != SubGhzRepeaterStateOff) {
canvas_draw_str(canvas, 59, 46, "Repeater...");
} else if(model->hopping_enabled) {
canvas_draw_str(canvas, 59, 46, "Hopper scan...");
} else {
canvas_draw_str(canvas, 59, 46, "Fixed scan...");
@@ -545,18 +550,36 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) {
},
false);
consumed = true;
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
with_view_model(
subghz_receiver->view,
SubGhzViewReceiverModel * model,
{
if(model->history_item != 0) {
subghz_receiver->callback(
SubGhzCustomEventViewReceiverOK, subghz_receiver->context);
}
},
false);
consumed = true;
} else if(event->key == InputKeyOk) {
SubGhzCustomEvent new_event;
switch(event->type) {
case InputTypeShort:
new_event = SubGhzCustomEventViewReceiverOK;
break;
case InputTypeLong:
new_event = SubGhzCustomEventViewReceiverOKLong;
break;
case InputTypeRelease:
new_event = SubGhzCustomEventViewReceiverOKRelease;
break;
default:
new_event = 0;
break;
}
if(new_event) {
with_view_model(
subghz_receiver->view,
SubGhzViewReceiverModel * model,
{
if(model->history_item != 0) {
subghz_receiver->callback(new_event, subghz_receiver->context);
}
},
false);
consumed = true;
}
}
if(consumed) {
@@ -595,6 +618,7 @@ void subghz_view_receiver_exit(void* context) {
model->nodraw = false;
model->hopping_enabled = false;
model->bin_raw_enabled = false;
model->repeater_state = SubGhzRepeaterStateOff;
},
false);
furi_timer_stop(subghz_receiver->timer);

View File

@@ -33,7 +33,8 @@ void subghz_view_receiver_add_data_statusbar(
const char* preset_str,
const char* history_stat_str,
bool hopping_enabled,
bool bin_raw_enabled);
bool bin_raw_enabled,
SubGhzRepeaterState repeater_enabled);
void subghz_view_receiver_set_radio_device_type(
SubGhzViewReceiver* subghz_receiver,

View File

@@ -594,9 +594,10 @@ void variable_item_set_current_value_text(VariableItem* item, const char* curren
void variable_item_set_locked(VariableItem* item, bool locked, const char* locked_message) {
item->locked = locked;
if(locked) {
furi_assert(locked_message);
if(locked_message) {
furi_string_set(item->locked_message, locked_message);
} else if(locked && furi_string_empty(item->locked_message)) {
furi_string_set(item->locked_message, "Locked!");
}
}