mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2025-02-17 05:48:33 +00:00
Using TxRx from subghz
This commit is contained in:
parent
26bcebd575
commit
311533a0ac
10 changed files with 310 additions and 333 deletions
|
@ -1,5 +1,7 @@
|
|||
#include "subrem_presets.h"
|
||||
|
||||
#define TAG "SubRemPresets"
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc() {
|
||||
SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset));
|
||||
|
||||
|
@ -8,6 +10,8 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() {
|
|||
sub_preset->protocaol_name = furi_string_alloc();
|
||||
sub_preset->label = furi_string_alloc_set_str("N/A");
|
||||
|
||||
sub_preset->freq_preset.name = furi_string_alloc();
|
||||
|
||||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
sub_preset->load_state = SubRemLoadSubStateNotSet;
|
||||
|
||||
|
@ -22,6 +26,8 @@ void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) {
|
|||
furi_string_free(sub_preset->file_path);
|
||||
flipper_format_free(sub_preset->fff_data);
|
||||
|
||||
furi_string_free(sub_preset->freq_preset.name);
|
||||
|
||||
free(sub_preset);
|
||||
}
|
||||
|
||||
|
@ -38,3 +44,136 @@ void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) {
|
|||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
sub_preset->load_state = SubRemLoadSubStateNotSet;
|
||||
}
|
||||
|
||||
SubRemLoadSubState subrem_sub_preset_load(
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file) {
|
||||
furi_assert(sub_preset);
|
||||
furi_assert(txrx);
|
||||
furi_assert(fff_data_file);
|
||||
|
||||
Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data);
|
||||
|
||||
SubRemLoadSubState ret;
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
uint32_t repeat = 200;
|
||||
|
||||
ret = SubRemLoadSubStateError;
|
||||
|
||||
do {
|
||||
stream_clean(fff_data_stream);
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Type or version mismatch");
|
||||
break;
|
||||
}
|
||||
|
||||
SubGhzSetting* setting = subghz_txrx_get_setting(txrx); // txrx->setting;
|
||||
|
||||
//Load frequency or using default from settings
|
||||
ret = SubRemLoadSubStateErrorFreq;
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||
FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency");
|
||||
sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting);
|
||||
} else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) {
|
||||
FURI_LOG_E(TAG, "This frequency can only be used for RX");
|
||||
break;
|
||||
}
|
||||
sub_preset->freq_preset.frequency = temp_data32;
|
||||
|
||||
//Load preset
|
||||
ret = SubRemLoadSubStateErrorMod;
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set_str(
|
||||
temp_str, subghz_txrx_get_preset_name(txrx, furi_string_get_cstr(temp_str)));
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) {
|
||||
FURI_LOG_E(TAG, "CUSTOM preset is not supported");
|
||||
break;
|
||||
// TODO Custom preset loading logic if need
|
||||
// sub_preset->freq_preset.preset_index =
|
||||
// subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->freq_preset.name, temp_str);
|
||||
|
||||
// Load protocol
|
||||
ret = SubRemLoadSubStateErrorProtocol;
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperFormat* fff_data = sub_preset->fff_data;
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
|
||||
//if RAW
|
||||
subghz_protocol_raw_gen_fff_data(
|
||||
fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
stream_copy_full(
|
||||
flipper_format_get_raw_stream(fff_data_file),
|
||||
flipper_format_get_raw_stream(fff_data));
|
||||
}
|
||||
|
||||
if(subghz_txrx_load_decoder_by_name_protocol(txrx, furi_string_get_cstr(temp_str))) {
|
||||
SubGhzProtocolStatus status =
|
||||
subghz_protocol_decoder_base_deserialize(subghz_txrx_get_decoder(txrx), fff_data);
|
||||
if(status != SubGhzProtocolStatusOk) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol not found");
|
||||
break;
|
||||
}
|
||||
|
||||
const SubGhzProtocol* protocol = subghz_txrx_get_decoder(txrx)->protocol;
|
||||
|
||||
if(protocol->flag & SubGhzProtocolFlag_Send) {
|
||||
if((protocol->type == SubGhzProtocolTypeStatic) ||
|
||||
(protocol->type == SubGhzProtocolTypeDynamic) ||
|
||||
// TODO: BINRAW It probably works, but checks are needed.
|
||||
// (protocol->type == SubGhzProtocolTypeBinRAW) ||
|
||||
(protocol->type == SubGhzProtocolTypeRAW)) {
|
||||
sub_preset->type = protocol->type;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsuported Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->protocaol_name, temp_str);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol does not support transmission");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable Repeat");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = SubRemLoadSubStateOK;
|
||||
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label));
|
||||
#endif
|
||||
} while(false);
|
||||
|
||||
furi_string_free(temp_str);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
#include "subrem_types.h"
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
#include "../../subghz/helpers/subghz_txrx.h"
|
||||
|
||||
typedef struct {
|
||||
FuriString* name;
|
||||
uint32_t frequency;
|
||||
uint8_t* data;
|
||||
// size_t preset_index; // Need for custom preset
|
||||
} FreqPreset;
|
||||
|
||||
// Sub File preset
|
||||
|
@ -20,8 +22,17 @@ typedef struct {
|
|||
SubRemLoadSubState load_state;
|
||||
} SubRemSubFilePreset;
|
||||
|
||||
typedef struct {
|
||||
SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount];
|
||||
} SubRemMapPreset;
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc();
|
||||
|
||||
void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset);
|
||||
|
||||
void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset);
|
||||
|
||||
SubRemLoadSubState subrem_sub_preset_load(
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file);
|
||||
|
|
|
@ -26,7 +26,7 @@ typedef enum {
|
|||
} SubRemViewID;
|
||||
|
||||
typedef enum {
|
||||
SubRemLoadSubStateNotSet,
|
||||
SubRemLoadSubStateNotSet = 0,
|
||||
SubRemLoadSubStatePreloaded,
|
||||
SubRemLoadSubStateError,
|
||||
SubRemLoadSubStateErrorNoFile,
|
||||
|
|
|
@ -4,7 +4,8 @@ void subrem_scene_openmapfile_on_enter(void* context) {
|
|||
SubGhzRemoteApp* app = context;
|
||||
SubRemLoadMapState load_state = subrem_load_from_file(app);
|
||||
|
||||
if(load_state == SubRemLoadMapStateError) {
|
||||
if(load_state != SubRemLoadMapStateOK && load_state != SubRemLoadMapStateNotAllOK &&
|
||||
load_state != SubRemLoadMapStateBack) {
|
||||
#ifdef SUBREM_LIGHT
|
||||
dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file");
|
||||
#else
|
||||
|
|
|
@ -37,17 +37,16 @@ static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) {
|
|||
|
||||
static bool subrem_scene_remote_update_data_show(void* context) {
|
||||
SubGhzRemoteApp* app = context;
|
||||
bool ret = false;
|
||||
|
||||
subrem_view_remote_add_data_to_show(
|
||||
app->subrem_remote_view,
|
||||
furi_string_get_cstr(app->map_preset->subs_preset[0]->label),
|
||||
furi_string_get_cstr(app->map_preset->subs_preset[1]->label),
|
||||
furi_string_get_cstr(app->map_preset->subs_preset[2]->label),
|
||||
furi_string_get_cstr(app->map_preset->subs_preset[3]->label),
|
||||
furi_string_get_cstr(app->map_preset->subs_preset[4]->label));
|
||||
const char* labels[SubRemSubKeyNameMaxCount];
|
||||
|
||||
return ret;
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
labels[i] = furi_string_get_cstr(app->map_preset->subs_preset[i]->label);
|
||||
}
|
||||
|
||||
subrem_view_remote_add_data_to_show(app->subrem_remote_view, labels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subrem_scene_remote_on_enter(void* context) {
|
||||
|
@ -81,32 +80,37 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
|||
event.event == SubRemCustomEventViewRemoteStartOK) {
|
||||
// Start sending sub
|
||||
subrem_tx_stop_sub(app, true);
|
||||
app->chusen_sub = subrem_scene_remote_event_to_index(event.event);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading);
|
||||
if(subrem_tx_start_sub(
|
||||
app,
|
||||
app->map_preset->subs_preset[app->chusen_sub],
|
||||
subrem_scene_remote_raw_callback_end_tx)) {
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub);
|
||||
|
||||
uint8_t chusen_sub = subrem_scene_remote_event_to_index(event.event);
|
||||
app->chusen_sub = chusen_sub;
|
||||
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateLoading, chusen_sub);
|
||||
|
||||
if(subrem_tx_start_sub(app, app->map_preset->subs_preset[chusen_sub])) {
|
||||
if(app->map_preset->subs_preset[chusen_sub]->type == SubGhzProtocolTypeRAW) {
|
||||
subghz_txrx_set_raw_file_encoder_worker_callback_end(
|
||||
app->txrx, subrem_scene_remote_raw_callback_end_tx, app);
|
||||
}
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateSending);
|
||||
app->subrem_remote_view, SubRemViewRemoteStateSending, chusen_sub);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
} else {
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubRemCustomEventViewRemoteForcedStop) {
|
||||
subrem_tx_stop_sub(app, true);
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
return true;
|
||||
} else if(event.event == SubRemCustomEventViewRemoteStop) {
|
||||
if(subrem_tx_stop_sub(app, false)) {
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
@ -123,8 +127,7 @@ void subrem_scene_remote_on_exit(void* context) {
|
|||
|
||||
subrem_tx_stop_sub(app, true);
|
||||
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
|
|
@ -79,23 +79,9 @@ SubGhzRemoteApp* subghz_remote_app_alloc() {
|
|||
app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc();
|
||||
}
|
||||
|
||||
app->setting = subghz_setting_alloc();
|
||||
subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"));
|
||||
app->txrx = subghz_txrx_alloc();
|
||||
|
||||
app->environment = subghz_environment_alloc();
|
||||
|
||||
subghz_environment_load_keystore(app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes"));
|
||||
subghz_environment_load_keystore(
|
||||
app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
|
||||
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/came_atomo"));
|
||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/nice_flor_s"));
|
||||
subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry);
|
||||
|
||||
app->receiver = subghz_receiver_alloc_init(app->environment);
|
||||
subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app);
|
||||
|
||||
app->tx_running = false;
|
||||
|
||||
|
@ -132,9 +118,7 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) {
|
|||
scene_manager_free(app->scene_manager);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
subghz_receiver_free(app->receiver);
|
||||
subghz_environment_free(app->environment);
|
||||
subghz_setting_free(app->setting);
|
||||
subghz_txrx_free(app->txrx);
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
subrem_sub_file_preset_free(app->map_preset->subs_preset[i]);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
|
||||
#include "../subghz/helpers/subghz_txrx_i.h"
|
||||
|
||||
// #include <lib/subghz/protocols/keeloq.h>
|
||||
// #include <lib/subghz/protocols/star_line.h>
|
||||
|
||||
|
@ -11,6 +13,12 @@
|
|||
|
||||
#define TAG "SubGhzRemote"
|
||||
|
||||
// XXX Using TxRx
|
||||
// [x] use TxRx preset subrem_sub_preset_load & subrem_tx_start_sub
|
||||
// [x] subrem_sub_preset_load & drop subrem_set_preset_data
|
||||
// [x] subrem_tx_start_sub
|
||||
// [x] subrem_tx_stop_sub
|
||||
|
||||
static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = {
|
||||
[SubRemSubKeyNameUp] = {"UP", "ULABEL"},
|
||||
[SubRemSubKeyNameDown] = {"DOWN", "DLABEL"},
|
||||
|
@ -19,30 +27,7 @@ static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = {
|
|||
[SubRemSubKeyNameOk] = {"OK", "OKLABEL"},
|
||||
};
|
||||
|
||||
static bool
|
||||
subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) {
|
||||
const char* preset_name = "";
|
||||
if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
|
||||
preset_name = "AM270";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
|
||||
preset_name = "AM650";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
|
||||
preset_name = "FM238";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
|
||||
preset_name = "FM476";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) {
|
||||
// preset_name = "CUSTOM";
|
||||
return false;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unknown preset");
|
||||
return false;
|
||||
}
|
||||
size_t preset_index = subghz_setting_get_inx_preset_by_name(setting, preset_name);
|
||||
freq_preset->data = subghz_setting_get_preset_data(setting, preset_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
void subrem_map_preset_reset(SubRemMapPreset* map_preset) {
|
||||
static void subrem_map_preset_reset(SubRemMapPreset* map_preset) {
|
||||
furi_assert(map_preset);
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
|
@ -50,12 +35,61 @@ void subrem_map_preset_reset(SubRemMapPreset* map_preset) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) {
|
||||
furi_assert(app);
|
||||
static SubRemLoadMapState subrem_map_preset_check(
|
||||
SubRemMapPreset* map_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file) {
|
||||
furi_assert(map_preset);
|
||||
furi_assert(txrx);
|
||||
|
||||
bool all_loaded = true;
|
||||
SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile;
|
||||
|
||||
SubRemLoadSubState sub_preset_loaded;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = map_preset->subs_preset[i];
|
||||
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorNoFile;
|
||||
|
||||
if(furi_string_empty(sub_preset->file_path)) {
|
||||
// FURI_LOG_I(TAG, "Empty file path");
|
||||
} else if(!flipper_format_file_open_existing(
|
||||
fff_data_file, furi_string_get_cstr(sub_preset->file_path))) {
|
||||
FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
sub_preset_loaded = subrem_sub_preset_load(sub_preset, txrx, fff_data_file);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Load file state logic
|
||||
// Label depending on the state
|
||||
// Move to remote scene
|
||||
|
||||
if(sub_preset_loaded != SubRemLoadSubStateOK) {
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
all_loaded = false;
|
||||
} else {
|
||||
ret = SubRemLoadMapStateNotAllOK;
|
||||
}
|
||||
|
||||
if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) {
|
||||
ret = SubRemLoadMapStateOK;
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* fff_data_file) {
|
||||
furi_assert(map_preset);
|
||||
bool ret = false;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = app->map_preset->subs_preset[i];
|
||||
sub_preset = map_preset->subs_preset[i];
|
||||
if(!flipper_format_read_string(
|
||||
fff_data_file, map_file_labels[i][0], sub_preset->file_path)) {
|
||||
#if FURI_DEBUG
|
||||
|
@ -69,8 +103,13 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data
|
|||
#if FURI_DEBUG
|
||||
FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]);
|
||||
#endif
|
||||
// TODO move to remote scene
|
||||
path_extract_filename(sub_preset->file_path, sub_preset->label, true);
|
||||
ret = true;
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
if(ret) {
|
||||
// Preload seccesful
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
|
@ -78,157 +117,14 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data
|
|||
map_file_labels[i][0],
|
||||
furi_string_get_cstr(sub_preset->label),
|
||||
furi_string_get_cstr(sub_preset->file_path));
|
||||
ret = true;
|
||||
sub_preset->load_state = SubRemLoadSubStatePreloaded;
|
||||
}
|
||||
|
||||
flipper_format_rewind(fff_data_file);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SubRemLoadMapState
|
||||
subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) {
|
||||
furi_assert(app);
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
bool all_loaded = true;
|
||||
SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile;
|
||||
SubRemLoadSubState sub_preset_loaded;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
uint32_t repeat = 200;
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = app->map_preset->subs_preset[i];
|
||||
if(furi_string_empty(sub_preset->file_path)) {
|
||||
// FURI_LOG_I(TAG, "Empty file path");
|
||||
continue;
|
||||
}
|
||||
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorNoFile;
|
||||
|
||||
repeat = 200;
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(
|
||||
fff_data_file, furi_string_get_cstr(sub_preset->file_path))) {
|
||||
FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Type or version mismatch");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load frequency
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorFreq;
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||
FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency");
|
||||
sub_preset->freq_preset.frequency =
|
||||
subghz_setting_get_default_frequency(app->setting);
|
||||
} else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) {
|
||||
FURI_LOG_E(TAG, "This frequency can only be used for RX");
|
||||
break;
|
||||
} else {
|
||||
sub_preset->freq_preset.frequency = temp_data32;
|
||||
}
|
||||
|
||||
//Load preset
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorMod;
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subrem_set_preset_data(
|
||||
app->setting, &sub_preset->freq_preset, furi_string_get_cstr(temp_str))) {
|
||||
FURI_LOG_E(TAG, "Cannot load preset.");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load protocol
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorProtocol;
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperFormat* fff_data = sub_preset->fff_data;
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
|
||||
//if RAW
|
||||
subghz_protocol_raw_gen_fff_data(
|
||||
fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
stream_copy_full(
|
||||
flipper_format_get_raw_stream(fff_data_file),
|
||||
flipper_format_get_raw_stream(fff_data));
|
||||
}
|
||||
|
||||
const SubGhzProtocolRegistry* protocol_registry_items =
|
||||
subghz_environment_get_protocol_registry(app->environment);
|
||||
|
||||
const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name(
|
||||
protocol_registry_items, furi_string_get_cstr(temp_str));
|
||||
|
||||
if(!protocol) {
|
||||
FURI_LOG_E(TAG, "Protocol not found");
|
||||
break;
|
||||
} else if(protocol->flag & SubGhzProtocolFlag_Send) {
|
||||
if((protocol->type == SubGhzProtocolTypeStatic) ||
|
||||
(protocol->type == SubGhzProtocolTypeDynamic) ||
|
||||
// (protocol->type == SubGhzProtocolTypeBinRAW) || // TODO: BINRAW
|
||||
(protocol->type == SubGhzProtocolTypeRAW)) {
|
||||
sub_preset->type = protocol->type;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsuported Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->protocaol_name, temp_str);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol does not support transmission");
|
||||
}
|
||||
|
||||
if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable Repeat");
|
||||
break;
|
||||
}
|
||||
|
||||
sub_preset_loaded = SubRemLoadSubStateOK;
|
||||
ret = SubRemLoadMapStateNotAllOK;
|
||||
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label));
|
||||
#endif
|
||||
} while(false);
|
||||
|
||||
// TODO:
|
||||
// Load file state logic
|
||||
// Label depending on the state
|
||||
// Move to remote scene
|
||||
|
||||
if(sub_preset_loaded != SubRemLoadSubStateOK) {
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
all_loaded = false;
|
||||
}
|
||||
|
||||
if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) {
|
||||
ret = SubRemLoadMapStateOK;
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
}
|
||||
furi_string_free(temp_str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) {
|
||||
furi_assert(app);
|
||||
furi_assert(file_path);
|
||||
|
@ -247,13 +143,13 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p
|
|||
FURI_LOG_E(TAG, "Could not open MAP file %s", file_path);
|
||||
ret = SubRemLoadMapStateErrorOpenError;
|
||||
} else {
|
||||
if(!subrem_map_preset_load(app, fff_data_file)) {
|
||||
if(!subrem_map_preset_load(app->map_preset, fff_data_file)) {
|
||||
FURI_LOG_E(TAG, "Could no Sub file path in MAP file");
|
||||
// ret = // error for popup
|
||||
} else if(!flipper_format_file_close(fff_data_file)) {
|
||||
ret = SubRemLoadMapStateErrorOpenError;
|
||||
} else {
|
||||
ret = subrem_map_preset_check(app, fff_data_file);
|
||||
ret = subrem_map_preset_check(app->map_preset, app->txrx, fff_data_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,9 +168,9 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) {
|
||||
bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* sub_file_name) {
|
||||
furi_assert(flipper_format);
|
||||
furi_assert(dev_file_name);
|
||||
furi_assert(sub_file_name);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
@ -283,19 +179,19 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev
|
|||
uint32_t repeat = 200;
|
||||
FuriString* file_dir = furi_string_alloc();
|
||||
|
||||
path_extract_dirname(dev_file_name, file_dir);
|
||||
path_extract_dirname(sub_file_name, file_dir);
|
||||
do {
|
||||
// removing additional fields
|
||||
flipper_format_delete_key(flipper_format, "Repeat");
|
||||
// flipper_format_delete_key(flipper_format, "Manufacture");
|
||||
|
||||
if(!storage_simply_remove(storage, dev_file_name)) {
|
||||
if(!storage_simply_remove(storage, sub_file_name)) {
|
||||
break;
|
||||
}
|
||||
|
||||
//ToDo check Write
|
||||
stream_seek(flipper_format_stream, 0, StreamOffsetFromStart);
|
||||
stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS);
|
||||
stream_save_to_file(flipper_format_stream, storage, sub_file_name, FSOM_CREATE_ALWAYS);
|
||||
|
||||
if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable Repeat");
|
||||
|
@ -310,10 +206,16 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev
|
|||
return saved;
|
||||
}
|
||||
|
||||
bool subrem_tx_start_sub(
|
||||
SubGhzRemoteApp* app,
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzProtocolEncoderRAWCallbackEnd callback) {
|
||||
void subrem_save_active_sub(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzRemoteApp* app = context;
|
||||
|
||||
SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub];
|
||||
subrem_save_protocol_to_file(
|
||||
sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
}
|
||||
|
||||
bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(app);
|
||||
furi_assert(sub_preset);
|
||||
bool ret = false;
|
||||
|
@ -321,88 +223,44 @@ bool subrem_tx_start_sub(
|
|||
subrem_tx_stop_sub(app, true);
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeUnknown) {
|
||||
return false;
|
||||
}
|
||||
ret = false;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label));
|
||||
|
||||
FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label));
|
||||
subghz_txrx_load_decoder_by_name_protocol(
|
||||
app->txrx, furi_string_get_cstr(sub_preset->protocaol_name));
|
||||
|
||||
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
||||
keeloq_reset_original_btn();
|
||||
subghz_custom_btns_reset();
|
||||
subghz_txrx_set_preset(
|
||||
app->txrx,
|
||||
furi_string_get_cstr(sub_preset->freq_preset.name),
|
||||
sub_preset->freq_preset.frequency,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
do {
|
||||
flipper_format_rewind(sub_preset->fff_data); //
|
||||
|
||||
app->transmitter = subghz_transmitter_alloc_init(
|
||||
app->environment, furi_string_get_cstr(sub_preset->protocaol_name));
|
||||
|
||||
if(app->transmitter) {
|
||||
if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) !=
|
||||
SubGhzProtocolStatusOk) {
|
||||
FURI_LOG_E(TAG, "Deserialize error!");
|
||||
break;
|
||||
}
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
|
||||
furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency);
|
||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
if(!furi_hal_subghz_tx()) {
|
||||
FURI_LOG_E(TAG, "Sending not allowed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeRAW) {
|
||||
subghz_protocol_raw_file_encoder_worker_set_callback_end(
|
||||
(SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(
|
||||
app->transmitter),
|
||||
callback,
|
||||
app);
|
||||
}
|
||||
|
||||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter);
|
||||
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
||||
keeloq_reset_original_btn();
|
||||
subghz_custom_btns_reset();
|
||||
|
||||
if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) {
|
||||
ret = true;
|
||||
}
|
||||
} while(false);
|
||||
}
|
||||
|
||||
app->tx_running = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void subghz_tx_stop(SubGhzRemoteApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
//Stop TX
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
|
||||
subghz_transmitter_stop(app->transmitter);
|
||||
subghz_transmitter_free(app->transmitter);
|
||||
furi_hal_subghz_idle();
|
||||
}
|
||||
|
||||
bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) {
|
||||
furi_assert(app);
|
||||
SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub];
|
||||
|
||||
if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) {
|
||||
// SubRemSubKeyTypeRawKey)) {
|
||||
// XXX drop app->tx_running
|
||||
if(app->tx_running) {
|
||||
subghz_tx_stop(app);
|
||||
subghz_txrx_stop(app->txrx);
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeDynamic) {
|
||||
subrem_save_protocol_to_file(
|
||||
sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
|
||||
keeloq_reset_mfname();
|
||||
keeloq_reset_kl_type();
|
||||
keeloq_reset_original_btn();
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "helpers/subrem_types.h"
|
||||
#include "helpers/subrem_presets.h"
|
||||
|
||||
#include "../subghz/helpers/subghz_txrx.h"
|
||||
|
||||
#include <assets_icons.h>
|
||||
|
||||
#include "views/remote.h"
|
||||
|
@ -31,9 +33,6 @@
|
|||
#define SUBREM_APP_FOLDER EXT_PATH("subghz_remote")
|
||||
#define SUBREM_MAX_LEN_NAME 64
|
||||
|
||||
typedef struct {
|
||||
SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount];
|
||||
} SubRemMapPreset;
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
|
@ -49,10 +48,7 @@ typedef struct {
|
|||
|
||||
SubRemMapPreset* map_preset;
|
||||
|
||||
SubGhzSetting* setting;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzTransmitter* transmitter;
|
||||
SubGhzTxRx* txrx;
|
||||
|
||||
bool tx_running;
|
||||
|
||||
|
@ -61,9 +57,8 @@ typedef struct {
|
|||
|
||||
SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app);
|
||||
|
||||
bool subrem_tx_start_sub(
|
||||
SubGhzRemoteApp* app,
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzProtocolEncoderRAWCallbackEnd callback);
|
||||
bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset);
|
||||
|
||||
bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced);
|
||||
bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced);
|
||||
|
||||
void subrem_save_active_sub(void* context);
|
|
@ -41,24 +41,18 @@ void subrem_view_remote_set_callback(
|
|||
subrem_view_remote->context = context;
|
||||
}
|
||||
|
||||
void subrem_view_remote_add_data_to_show(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
const char* up_label,
|
||||
const char* down_label,
|
||||
const char* left_label,
|
||||
const char* right_label,
|
||||
const char* ok_label) {
|
||||
void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels) {
|
||||
furi_assert(subrem_view_remote);
|
||||
|
||||
with_view_model(
|
||||
subrem_view_remote->view,
|
||||
SubRemViewRemoteModel * model,
|
||||
{
|
||||
strncpy(model->up_label, up_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->down_label, down_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->left_label, left_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->up_label, labels[0], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->down_label, labels[1], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->left_label, labels[2], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->right_label, labels[3], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->ok_label, labels[4], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
|
||||
// furi_string_set(model->up_label, up_label);
|
||||
// furi_string_set(model->down_label, down_label);
|
||||
|
@ -69,23 +63,21 @@ void subrem_view_remote_add_data_to_show(
|
|||
true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn) {
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state,
|
||||
uint8_t presed_btn) {
|
||||
furi_assert(subrem_view_remote);
|
||||
with_view_model(
|
||||
subrem_view_remote->view,
|
||||
SubRemViewRemoteModel * model,
|
||||
{ model->pressed_btn = presed_btn; },
|
||||
{
|
||||
model->state = state;
|
||||
model->pressed_btn = presed_btn;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state) {
|
||||
furi_assert(subrem_view_remote);
|
||||
with_view_model(
|
||||
subrem_view_remote->view, SubRemViewRemoteModel * model, { model->state = state; }, true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
|
|
@ -24,15 +24,9 @@ void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote);
|
|||
|
||||
View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote);
|
||||
|
||||
void subrem_view_remote_add_data_to_show(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
const char* up_label,
|
||||
const char* down_label,
|
||||
const char* left_label,
|
||||
const char* right_label,
|
||||
const char* ok_label);
|
||||
void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels);
|
||||
|
||||
void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn);
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state);
|
||||
SubRemViewRemoteState state,
|
||||
uint8_t presed_btn);
|
Loading…
Add table
Reference in a new issue