unleashed-firmware/applications/main/subghz/scenes/subghz_scene_read_raw.c

351 lines
14 KiB
C
Raw Normal View History

#include "../subghz_i.h"
#include "../views/subghz_read_raw.h"
[FL-2183] [FL-2209] Dolphin Deeds, Level up, assets generation, refactoring (#965) * Desktop: cleanup headers * Get loader pubsub via record * [FL-2183] Dolphin refactoring 2022.01 * Restruct animations assets structure * Rename assets * Cleanup headers * Update Recording animation * Add BadBattery animation * Provide loader's pubsub via record * Fix load/unload animations * Scripts: add flipper format support, initial dolphin packager rework. Assets: internal and external dolphin. * Sync internal meta.txt and manifest.txt * Reorder, rename dolphin assets * Split essential generated assets * Add ReadMe for dolphin assets * Separate essential blocking animations * Scripts: full dolphin validation before packaging * Assets, Scripts: dolphin external resources packer * Github: update codeowners * Scripts: proper slots handling in dolphin animation meta * Scripts: correct frames enumeration and fix compiled assets. * [FL-2209] Add Dolphin Deeds points and many more * Remove excess frame_rate * Change dolphin assets directory * Scripts: add internal resource support to dolphin compiler * Scripts: add internal assets generation, renaming * Scripts: correct assert, renaming * Code cleanup, documentation, fixes * Update Levelup animations * Rename essential -> blocking * Fix Unlocked hint * Scripts: rewrite Templite compiller, replace regexps with token parser, split block types into code and variable blocks. Update dolphin templates. * Documentation: add key combos description and use information * Scripts: cleanup templit, more debug info and add dev comment Co-authored-by: あく <alleteam@gmail.com>
2022-01-29 09:20:41 +00:00
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/raw.h>
#include <lib/toolbox/path.h>
#include <float_tools.h>
2022-06-27 22:54:37 +00:00
#define RAW_FILE_NAME "RAW_"
#define TAG "SubGhzSceneReadRAW"
bool subghz_scene_read_raw_update_filename(SubGhz* subghz) {
bool ret = false;
//set the path to read the file
2023-05-05 00:51:16 +00:00
FuriString* temp_str = furi_string_alloc();
do {
2023-05-09 18:54:56 +00:00
FlipperFormat* fff_data = subghz_txrx_get_fff_data(subghz->txrx);
2023-05-09 18:20:35 +00:00
if(!flipper_format_rewind(fff_data)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
2023-05-09 18:20:35 +00:00
if(!flipper_format_read_string(fff_data, "File_name", temp_str)) {
FURI_LOG_E(TAG, "Missing File_name");
break;
}
furi_string_set(subghz->file_path, temp_str);
ret = true;
} while(false);
furi_string_free(temp_str);
return ret;
}
static void subghz_scene_read_raw_update_statusbar(void* context) {
furi_assert(context);
SubGhz* subghz = context;
2023-05-05 00:51:16 +00:00
FuriString* frequency_str = furi_string_alloc();
FuriString* modulation_str = furi_string_alloc();
#ifdef SUBGHZ_EXT_PRESET_NAME
2023-05-09 18:54:56 +00:00
subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, true);
#else
2023-05-10 20:28:09 +00:00
subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, false);
#endif
subghz_read_raw_add_data_statusbar(
subghz->subghz_read_raw,
furi_string_get_cstr(frequency_str),
furi_string_get_cstr(modulation_str));
furi_string_free(frequency_str);
furi_string_free(modulation_str);
2023-06-18 17:25:40 +00:00
subghz_read_raw_set_radio_device_type(
subghz->subghz_read_raw, subghz_txrx_radio_device_get(subghz->txrx));
}
void subghz_scene_read_raw_callback(SubGhzCustomEvent event, void* context) {
furi_assert(context);
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
}
void subghz_scene_read_raw_callback_end_tx(void* context) {
furi_assert(context);
SubGhz* subghz = context;
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubGhzCustomEventViewReadRAWSendStop);
}
void subghz_scene_read_raw_on_enter(void* context) {
SubGhz* subghz = context;
2023-05-05 00:51:16 +00:00
FuriString* file_name = furi_string_alloc();
2023-05-09 18:20:35 +00:00
float threshold_rssi = subghz_threshold_rssi_get(subghz->threshold_rssi);
switch(subghz_rx_key_state_get(subghz)) {
case SubGhzRxKeyStateBack:
subghz_read_raw_set_status(
2023-05-09 18:20:35 +00:00
subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", threshold_rssi);
break;
case SubGhzRxKeyStateRAWLoad:
2022-06-01 13:07:53 +00:00
path_extract_filename(subghz->file_path, file_name, true);
subghz_read_raw_set_status(
subghz->subghz_read_raw,
SubGhzReadRAWStatusLoadKeyTX,
furi_string_get_cstr(file_name),
2023-05-09 18:20:35 +00:00
threshold_rssi);
break;
case SubGhzRxKeyStateRAWSave:
2022-06-01 13:07:53 +00:00
path_extract_filename(subghz->file_path, file_name, true);
subghz_read_raw_set_status(
subghz->subghz_read_raw,
SubGhzReadRAWStatusSaveKey,
furi_string_get_cstr(file_name),
2023-05-09 18:20:35 +00:00
threshold_rssi);
break;
default:
subghz_read_raw_set_status(
2023-05-09 18:20:35 +00:00
subghz->subghz_read_raw, SubGhzReadRAWStatusStart, "", threshold_rssi);
break;
}
2023-05-09 18:20:35 +00:00
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
#if SUBGHZ_LAST_SETTING_SAVE_PRESET
if(furi_string_empty(file_name)) {
subghz_txrx_set_preset_internal(
subghz->txrx,
subghz->last_settings->frequency,
subghz->last_settings->preset_index);
}
#endif
2023-05-09 18:20:35 +00:00
}
subghz_scene_read_raw_update_statusbar(subghz);
//set callback view raw
subghz_read_raw_set_callback(subghz->subghz_read_raw, subghz_scene_read_raw_callback, subghz);
2023-05-09 10:34:54 +00:00
furi_check(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_RAW_NAME));
//set filter RAW feed
2023-05-09 12:58:56 +00:00
subghz_txrx_receiver_set_filter(subghz->txrx, SubGhzProtocolFlag_RAW);
furi_string_free(file_name);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
}
bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
2023-05-09 18:20:35 +00:00
SubGhzProtocolDecoderRAW* decoder_raw =
(SubGhzProtocolDecoderRAW*)subghz_txrx_get_decoder(subghz->txrx);
if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case SubGhzCustomEventViewReadRAWBack:
2023-05-10 10:21:42 +00:00
subghz_txrx_stop(subghz->txrx);
//Stop save file
2023-05-09 18:20:35 +00:00
subghz_protocol_raw_save_to_file_stop(decoder_raw);
subghz->state_notifications = SubGhzNotificationStateIDLE;
//needed save?
if((subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey) ||
(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateBack)) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateExit);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else {
//Restore default setting
if(subghz->raw_send_only) {
subghz_txrx_set_default_preset(subghz->txrx, 0);
} else {
subghz_txrx_set_default_preset(subghz->txrx, subghz->last_settings->frequency);
}
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart)) {
scene_manager_stop(subghz->scene_manager);
view_dispatcher_stop(subghz->view_dispatcher);
}
}
}
consumed = true;
break;
case SubGhzCustomEventViewReadRAWTXRXStop:
subghz_txrx_stop(subghz->txrx);
subghz->state_notifications = SubGhzNotificationStateIDLE;
consumed = true;
break;
case SubGhzCustomEventViewReadRAWConfig:
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
consumed = true;
break;
case SubGhzCustomEventViewReadRAWErase:
if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey) {
if(subghz_scene_read_raw_update_filename(subghz)) {
furi_string_set(subghz->file_path_tmp, subghz->file_path);
subghz_delete_file(subghz);
}
}
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
notification_message(subghz->notifications, &sequence_reset_rgb);
consumed = true;
break;
case SubGhzCustomEventViewReadRAWMore:
if(subghz_file_available(subghz)) {
if(subghz_scene_read_raw_update_filename(subghz)) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW);
consumed = true;
} else {
furi_crash("SubGhz: RAW file name update error.");
}
} else {
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart)) {
scene_manager_stop(subghz->scene_manager);
view_dispatcher_stop(subghz->view_dispatcher);
}
}
break;
case SubGhzCustomEventViewReadRAWSendStart:
if(subghz_file_available(subghz) && subghz_scene_read_raw_update_filename(subghz)) {
//start send
subghz->state_notifications = SubGhzNotificationStateIDLE;
2023-05-09 18:54:56 +00:00
if(!subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx))) {
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack);
2023-05-06 13:36:15 +00:00
subghz_read_raw_set_status(
subghz->subghz_read_raw,
SubGhzReadRAWStatusIDLE,
"",
subghz_threshold_rssi_get(subghz->threshold_rssi));
} else {
if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneSaved) ||
!scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneStart)) {
dolphin_deed(DolphinDeedSubGhzSend);
}
2023-05-06 13:36:15 +00:00
// set callback end tx
2023-05-09 18:54:56 +00:00
subghz_txrx_set_raw_file_encoder_worker_callback_end(
2023-05-09 15:24:25 +00:00
subghz->txrx, subghz_scene_read_raw_callback_end_tx, subghz);
2023-05-06 13:36:15 +00:00
subghz->state_notifications = SubGhzNotificationStateTx;
}
} else {
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart)) {
scene_manager_stop(subghz->scene_manager);
view_dispatcher_stop(subghz->view_dispatcher);
}
}
consumed = true;
break;
case SubGhzCustomEventViewReadRAWSendStop:
subghz->state_notifications = SubGhzNotificationStateIDLE;
subghz_txrx_stop(subghz->txrx);
subghz_read_raw_stop_send(subghz->subghz_read_raw);
consumed = true;
break;
case SubGhzCustomEventViewReadRAWIDLE:
subghz_txrx_stop(subghz->txrx);
2023-05-09 18:20:35 +00:00
size_t spl_count = subghz_protocol_raw_get_sample_write(decoder_raw);
2023-05-09 18:20:35 +00:00
subghz_protocol_raw_save_to_file_stop(decoder_raw);
2023-05-05 00:51:16 +00:00
FuriString* temp_str = furi_string_alloc();
furi_string_printf(
2022-06-27 22:54:37 +00:00
temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION);
subghz_protocol_raw_gen_fff_data(
2023-06-18 17:25:40 +00:00
subghz_txrx_get_fff_data(subghz->txrx),
furi_string_get_cstr(temp_str),
subghz_txrx_radio_device_get_name(subghz->txrx));
furi_string_free(temp_str);
if(spl_count > 0) {
notification_message(subghz->notifications, &sequence_set_green_255);
} else {
notification_message(subghz->notifications, &sequence_reset_rgb);
}
subghz->state_notifications = SubGhzNotificationStateIDLE;
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey);
consumed = true;
break;
case SubGhzCustomEventViewReadRAWREC:
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateIDLE) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else {
2023-05-09 16:10:56 +00:00
SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx);
2023-05-09 18:20:35 +00:00
if(subghz_protocol_raw_save_to_file_init(decoder_raw, RAW_FILE_NAME, &preset)) {
dolphin_deed(DolphinDeedSubGhzRawRec);
2023-05-09 16:10:56 +00:00
subghz_txrx_rx_start(subghz->txrx);
subghz->state_notifications = SubGhzNotificationStateRx;
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey);
} else {
furi_string_set(subghz->error_str, "Function requires\nan SD card.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
}
}
consumed = true;
break;
case SubGhzCustomEventViewReadRAWSave:
if(subghz_file_available(subghz) && subghz_scene_read_raw_update_filename(subghz)) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSetRAW);
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
} else {
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart)) {
scene_manager_stop(subghz->scene_manager);
view_dispatcher_stop(subghz->view_dispatcher);
}
}
consumed = true;
break;
default:
break;
}
} else if(event.type == SceneManagerEventTypeTick) {
switch(subghz->state_notifications) {
case SubGhzNotificationStateRx:
notification_message(subghz->notifications, &sequence_blink_cyan_10);
2023-05-05 23:00:26 +00:00
subghz_read_raw_update_sample_write(
2023-05-09 18:20:35 +00:00
subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write(decoder_raw));
2023-06-18 17:25:40 +00:00
SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(
subghz->threshold_rssi, subghz_txrx_radio_device_get_rssi(subghz->txrx));
2023-05-05 23:00:26 +00:00
subghz_read_raw_add_data_rssi(
subghz->subghz_read_raw, ret_rssi.rssi, ret_rssi.is_above);
2023-05-09 18:20:35 +00:00
subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above);
break;
case SubGhzNotificationStateTx:
notification_message(subghz->notifications, &sequence_blink_magenta_10);
subghz_read_raw_update_sin(subghz->subghz_read_raw);
break;
default:
break;
}
}
return consumed;
}
void subghz_scene_read_raw_on_exit(void* context) {
SubGhz* subghz = context;
//Stop CC1101
subghz_txrx_stop(subghz->txrx);
subghz->state_notifications = SubGhzNotificationStateIDLE;
notification_message(subghz->notifications, &sequence_reset_rgb);
//filter restoration
2023-05-09 12:58:56 +00:00
subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter);
2023-02-20 15:55:53 +00:00
}