Merge pull request #492 from gid9798/subrem_main_and_maker

Subrem main and maker
This commit is contained in:
MX 2023-05-31 01:08:24 +03:00 committed by GitHub
commit 0a0109e2aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 217 additions and 247 deletions

View file

@ -9,11 +9,13 @@ typedef enum {
} SubRemEditMenuState; } SubRemEditMenuState;
typedef enum { typedef enum {
// SubmenuIndex // StartSubmenuIndex
SubmenuIndexSubRemEditMapFile = 0, SubmenuIndexSubRemEditMapFile = 0,
SubmenuIndexSubRemNewMapFile, SubmenuIndexSubRemNewMapFile,
#if FURI_DEBUG
SubmenuIndexSubRemRemoteView, SubmenuIndexSubRemRemoteView,
SubmenuIndexSubRemAbout, #endif
// SubmenuIndexSubRemAbout,
// EditSubmenuIndex // EditSubmenuIndex
EditSubmenuIndexEditLabel, EditSubmenuIndexEditLabel,
@ -45,8 +47,4 @@ typedef enum {
SubRemCustomEventSceneEditPreviewSaved, SubRemCustomEventSceneEditPreviewSaved,
SubRemCustomEventSceneNewName, SubRemCustomEventSceneNewName,
// // SceneStates
// SubRemSceneOpenMapFileStateOpen,
// SubRemSceneOpenMapFileStateEdit,
} SubRemCustomEvent; } SubRemCustomEvent;

View file

@ -147,8 +147,7 @@ SubRemLoadSubState subrem_sub_preset_load(
if(protocol->flag & SubGhzProtocolFlag_Send) { if(protocol->flag & SubGhzProtocolFlag_Send) {
if((protocol->type == SubGhzProtocolTypeStatic) || if((protocol->type == SubGhzProtocolTypeStatic) ||
(protocol->type == SubGhzProtocolTypeDynamic) || (protocol->type == SubGhzProtocolTypeDynamic) ||
// TODO: BINRAW It probably works, but checks are needed. (protocol->type == SubGhzProtocolTypeBinRAW) ||
// (protocol->type == SubGhzProtocolTypeBinRAW) ||
(protocol->type == SubGhzProtocolTypeRAW)) { (protocol->type == SubGhzProtocolTypeRAW)) {
sub_preset->type = protocol->type; sub_preset->type = protocol->type;
} else { } else {

View file

@ -23,10 +23,6 @@
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/subghz/subghz_setting.h>
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#define SUBREM_APP_FOLDER EXT_PATH("subghz_remote") #define SUBREM_APP_FOLDER EXT_PATH("subghz_remote")
#define SUBREM_MAX_LEN_NAME 64 #define SUBREM_MAX_LEN_NAME 64

View file

@ -12,6 +12,6 @@ App(
"dialogs", "dialogs",
], ],
icon="A_SubGHzRemote_14", icon="A_SubGHzRemote_14",
stack_size=4 * 1024, stack_size=2 * 1024,
order=11, order=11,
) )

View file

@ -1,12 +1,14 @@
#pragma once #pragma once
typedef enum { typedef enum {
//SubmenuIndex // StartSubmenuIndex
SubmenuIndexSubRemOpenMapFile, SubmenuIndexSubRemOpenMapFile = 0,
#if FURI_DEBUG
SubmenuIndexSubRemRemoteView, SubmenuIndexSubRemRemoteView,
SubmenuIndexSubRemAbout, #endif
// SubmenuIndexSubRemAbout,
//SubRemCustomEvent // SubRemCustomEvent
SubRemCustomEventViewRemoteStartUP = 100, SubRemCustomEventViewRemoteStartUP = 100,
SubRemCustomEventViewRemoteStartDOWN, SubRemCustomEventViewRemoteStartDOWN,
SubRemCustomEventViewRemoteStartLEFT, SubRemCustomEventViewRemoteStartLEFT,

View file

@ -8,7 +8,7 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() {
sub_preset->fff_data = flipper_format_string_alloc(); sub_preset->fff_data = flipper_format_string_alloc();
sub_preset->file_path = furi_string_alloc(); sub_preset->file_path = furi_string_alloc();
sub_preset->protocaol_name = furi_string_alloc(); sub_preset->protocaol_name = furi_string_alloc();
sub_preset->label = furi_string_alloc_set_str("N/A"); sub_preset->label = furi_string_alloc();
sub_preset->freq_preset.name = furi_string_alloc(); sub_preset->freq_preset.name = furi_string_alloc();
@ -34,7 +34,7 @@ void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) {
void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) {
furi_assert(sub_preset); furi_assert(sub_preset);
furi_string_set_str(sub_preset->label, "N/A"); furi_string_set_str(sub_preset->label, "");
furi_string_reset(sub_preset->protocaol_name); furi_string_reset(sub_preset->protocaol_name);
furi_string_reset(sub_preset->file_path); furi_string_reset(sub_preset->file_path);
@ -77,7 +77,7 @@ SubRemLoadSubState subrem_sub_preset_load(
break; break;
} }
SubGhzSetting* setting = subghz_txrx_get_setting(txrx); // txrx->setting; SubGhzSetting* setting = subghz_txrx_get_setting(txrx);
//Load frequency or using default from settings //Load frequency or using default from settings
ret = SubRemLoadSubStateErrorFreq; ret = SubRemLoadSubStateErrorFreq;
@ -147,8 +147,7 @@ SubRemLoadSubState subrem_sub_preset_load(
if(protocol->flag & SubGhzProtocolFlag_Send) { if(protocol->flag & SubGhzProtocolFlag_Send) {
if((protocol->type == SubGhzProtocolTypeStatic) || if((protocol->type == SubGhzProtocolTypeStatic) ||
(protocol->type == SubGhzProtocolTypeDynamic) || (protocol->type == SubGhzProtocolTypeDynamic) ||
// TODO: BINRAW It probably works, but checks are needed. (protocol->type == SubGhzProtocolTypeBinRAW) ||
// (protocol->type == SubGhzProtocolTypeBinRAW) ||
(protocol->type == SubGhzProtocolTypeRAW)) { (protocol->type == SubGhzProtocolTypeRAW)) {
sub_preset->type = protocol->type; sub_preset->type = protocol->type;
} else { } else {
@ -175,5 +174,6 @@ SubRemLoadSubState subrem_sub_preset_load(
} while(false); } while(false);
furi_string_free(temp_str); furi_string_free(temp_str);
sub_preset->load_state = ret;
return ret; return ret;
} }

View file

@ -1,9 +1,10 @@
#pragma once #pragma once
#include "subrem_types.h" #include "subrem_types.h"
#include "txrx/subghz_txrx.h"
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/subghz/protocols/protocol_items.h> #include <lib/subghz/types.h>
#include "../../subghz/helpers/subghz_txrx.h"
typedef struct { typedef struct {
FuriString* name; FuriString* name;

View file

@ -3,9 +3,8 @@
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
// TODO: File version/type logic #define SUBREM_APP_APP_FILE_VERSION 1
// #define SUBREM_APP_APP_FILE_VERSION 1 #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file"
// #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file"
#define SUBREM_APP_EXTENSION ".txt" #define SUBREM_APP_EXTENSION ".txt"
typedef enum { typedef enum {
@ -18,10 +17,7 @@ typedef enum {
} SubRemSubKeyName; } SubRemSubKeyName;
typedef enum { typedef enum {
SubRemViewSubmenu, SubRemViewIDSubmenu,
SubRemViewWidget,
SubRemViewPopup,
SubRemViewTextInput,
SubRemViewIDRemote, SubRemViewIDRemote,
} SubRemViewID; } SubRemViewID;
@ -29,6 +25,7 @@ typedef enum {
SubRemLoadSubStateNotSet = 0, SubRemLoadSubStateNotSet = 0,
SubRemLoadSubStatePreloaded, SubRemLoadSubStatePreloaded,
SubRemLoadSubStateError, SubRemLoadSubStateError,
SubRemLoadSubStateErrorIncorectPath,
SubRemLoadSubStateErrorNoFile, SubRemLoadSubStateErrorNoFile,
SubRemLoadSubStateErrorFreq, SubRemLoadSubStateErrorFreq,
SubRemLoadSubStateErrorMod, SubRemLoadSubStateErrorMod,

View file

@ -0,0 +1,4 @@
This is part of the official `SubGhz` app from [flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware/tree/3217f286f03da119398586daf94c0723d28b872a/applications/main/subghz)
With changes from [unleashed-firmware
](https://github.com/DarkFlippers/unleashed-firmware/tree/3eac6ccd48a3851cf5d63bf7899b387a293e5319/applications/main/subghz)

View file

@ -0,0 +1,3 @@
#pragma once
#include "../../../subghz/helpers/subghz_txrx.h"

View file

@ -1,3 +1,5 @@
#ifndef SUBREM_LIGHT
ADD_SCENE(subrem, start, Start) ADD_SCENE(subrem, start, Start)
ADD_SCENE(subrem, openmapfile, OpenMapFile) #endif
ADD_SCENE(subrem, open_map_file, OpenMapFile)
ADD_SCENE(subrem, remote, Remote) ADD_SCENE(subrem, remote, Remote)

View file

@ -0,0 +1,43 @@
#include "../subghz_remote_app_i.h"
void subrem_scene_open_map_file_on_enter(void* context) {
furi_assert(context);
SubGhzRemoteApp* app = context;
SubRemLoadMapState load_state = subrem_load_from_file(app);
if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) {
scene_manager_next_scene(app->scene_manager, SubRemSceneRemote);
} else {
if(load_state != SubRemLoadMapStateBack) {
#ifdef SUBREM_LIGHT
dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file");
#else
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter);
dialog_message_set_text(
message, "Can't load\nMap file", 64, 32, AlignCenter, AlignCenter);
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_show(app->dialogs, message);
dialog_message_free(message);
#endif
}
// TODO: Map Preset Reset
if(!scene_manager_previous_scene(app->scene_manager)) {
scene_manager_stop(app->scene_manager);
view_dispatcher_stop(app->view_dispatcher);
}
}
}
bool subrem_scene_open_map_file_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
UNUSED(event);
return false;
}
void subrem_scene_open_map_file_on_exit(void* context) {
UNUSED(context);
}

View file

@ -1,42 +0,0 @@
#include "../subghz_remote_app_i.h"
void subrem_scene_openmapfile_on_enter(void* context) {
SubGhzRemoteApp* app = context;
SubRemLoadMapState load_state = subrem_load_from_file(app);
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
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter);
dialog_message_set_text(message, "Can't load\nMap file", 64, 32, AlignCenter, AlignCenter);
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_show(app->dialogs, message);
dialog_message_free(message);
#endif
}
if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) {
scene_manager_next_scene(app->scene_manager, SubRemSceneRemote);
} else {
// TODO: Map Preset Reset
if(!scene_manager_search_and_switch_to_previous_scene(
app->scene_manager, SubRemSceneStart)) {
scene_manager_stop(app->scene_manager);
view_dispatcher_stop(app->view_dispatcher);
}
}
}
bool subrem_scene_openmapfile_on_event(void* context, SceneManagerEvent event) {
UNUSED(context);
UNUSED(event);
return false;
}
void subrem_scene_openmapfile_on_exit(void* context) {
UNUSED(context);
}

View file

@ -35,24 +35,10 @@ static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) {
return ret; return ret;
} }
static bool subrem_scene_remote_update_data_show(void* context) {
SubGhzRemoteApp* app = context;
const char* labels[SubRemSubKeyNameMaxCount];
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) { void subrem_scene_remote_on_enter(void* context) {
SubGhzRemoteApp* app = context; SubGhzRemoteApp* app = context;
subrem_scene_remote_update_data_show(app); subrem_view_remote_update_data_labels(app->subrem_remote_view, app->map_preset->subs_preset);
subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app); subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app);
@ -63,13 +49,9 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) {
SubGhzRemoteApp* app = context; SubGhzRemoteApp* app = context;
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubRemCustomEventViewRemoteBack) { if(event.event == SubRemCustomEventViewRemoteBack) {
if(!scene_manager_search_and_switch_to_previous_scene( if(!scene_manager_previous_scene(app->scene_manager)) {
app->scene_manager, SubRemSceneOpenMapFile)) { scene_manager_stop(app->scene_manager);
if(!scene_manager_search_and_switch_to_previous_scene( view_dispatcher_stop(app->view_dispatcher);
app->scene_manager, SubRemSceneStart)) {
scene_manager_stop(app->scene_manager);
view_dispatcher_stop(app->view_dispatcher);
}
} }
return true; return true;
} else if( } else if(

View file

@ -33,13 +33,11 @@ void subrem_scene_start_on_enter(void* context) {
// SubmenuIndexSubGhzRemoteAbout, // SubmenuIndexSubGhzRemoteAbout,
// subrem_scene_start_submenu_callback, // subrem_scene_start_submenu_callback,
// app); // app);
#ifndef SUBREM_LIGHT
// TODO: set scene state in subrem alloc submenu_set_selected_item(
// submenu_set_selected_item( submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart));
// submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); #endif
submenu_set_selected_item(submenu, SubmenuIndexSubRemOpenMapFile); view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDSubmenu);
view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu);
} }
bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) {
@ -50,6 +48,10 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSubRemOpenMapFile) { if(event.event == SubmenuIndexSubRemOpenMapFile) {
#ifndef SUBREM_LIGHT
scene_manager_set_scene_state(
app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemOpenMapFile);
#endif
scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile);
consumed = true; consumed = true;
} }

View file

@ -1,7 +1,5 @@
#include "subghz_remote_app_i.h" #include "subghz_remote_app_i.h"
#include <lib/subghz/protocols/protocol_items.h>
static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) {
furi_assert(context); furi_assert(context);
SubGhzRemoteApp* app = context; SubGhzRemoteApp* app = context;
@ -70,9 +68,9 @@ SubGhzRemoteApp* subghz_remote_app_alloc() {
// SubMenu // SubMenu
app->submenu = submenu_alloc(); app->submenu = submenu_alloc();
view_dispatcher_add_view( view_dispatcher_add_view(
app->view_dispatcher, SubRemViewSubmenu, submenu_get_view(app->submenu)); app->view_dispatcher, SubRemViewIDSubmenu, submenu_get_view(app->submenu));
//Dialog // Dialog
app->dialogs = furi_record_open(RECORD_DIALOGS); app->dialogs = furi_record_open(RECORD_DIALOGS);
// Remote view // Remote view
@ -91,12 +89,12 @@ SubGhzRemoteApp* subghz_remote_app_alloc() {
subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app); subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app);
app->tx_running = false;
#ifdef SUBREM_LIGHT #ifdef SUBREM_LIGHT
scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile);
#else #else
scene_manager_next_scene(app->scene_manager, SubRemSceneStart); scene_manager_next_scene(app->scene_manager, SubRemSceneStart);
scene_manager_set_scene_state(
app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemOpenMapFile);
#endif #endif
return app; return app;
@ -113,10 +111,10 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) {
furi_hal_subghz_init_radio_type(SubGhzRadioInternal); furi_hal_subghz_init_radio_type(SubGhzRadioInternal);
// Submenu // Submenu
view_dispatcher_remove_view(app->view_dispatcher, SubRemViewSubmenu); view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDSubmenu);
submenu_free(app->submenu); submenu_free(app->submenu);
//Dialog // Dialog
furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_DIALOGS);
// Remote view // Remote view

View file

@ -2,23 +2,18 @@
#include <lib/toolbox/path.h> #include <lib/toolbox/path.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/subghz/protocols/protocol_items.h> #include "helpers/txrx/subghz_txrx.h"
#include "../subghz/helpers/subghz_txrx_i.h"
// #include <lib/subghz/protocols/keeloq.h> // #include <lib/subghz/protocols/keeloq.h>
// #include <lib/subghz/protocols/star_line.h> // #include <lib/subghz/protocols/star_line.h>
#ifdef APP_SUBGHZREMOTE
#include <lib/subghz/protocols/protocol_items.h>
#include <lib/subghz/blocks/custom_btn.h> #include <lib/subghz/blocks/custom_btn.h>
#endif
#define TAG "SubGhzRemote" #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] = { static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = {
[SubRemSubKeyNameUp] = {"UP", "ULABEL"}, [SubRemSubKeyNameUp] = {"UP", "ULABEL"},
[SubRemSubKeyNameDown] = {"DOWN", "DLABEL"}, [SubRemSubKeyNameDown] = {"DOWN", "DLABEL"},
@ -45,30 +40,25 @@ static SubRemLoadMapState subrem_map_preset_check(
bool all_loaded = true; bool all_loaded = true;
SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile;
SubRemLoadSubState sub_preset_loaded; SubRemLoadSubState sub_loadig_state;
SubRemSubFilePreset* sub_preset; SubRemSubFilePreset* sub_preset;
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
sub_preset = map_preset->subs_preset[i]; sub_preset = map_preset->subs_preset[i];
sub_preset_loaded = SubRemLoadSubStateErrorNoFile; sub_loadig_state = SubRemLoadSubStateErrorNoFile;
if(furi_string_empty(sub_preset->file_path)) { if(furi_string_empty(sub_preset->file_path)) {
// FURI_LOG_I(TAG, "Empty file path"); // FURI_LOG_I(TAG, "Empty file path");
} else if(!flipper_format_file_open_existing( } else if(!flipper_format_file_open_existing(
fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { fff_data_file, furi_string_get_cstr(sub_preset->file_path))) {
sub_preset->load_state = SubRemLoadSubStateErrorNoFile;
FURI_LOG_W(TAG, "Error open file %s", 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 { } else {
sub_preset_loaded = subrem_sub_preset_load(sub_preset, txrx, fff_data_file); sub_loadig_state = subrem_sub_preset_load(sub_preset, txrx, fff_data_file);
} }
// TODO: if(sub_loadig_state != SubRemLoadSubStateOK) {
// 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; all_loaded = false;
} else { } else {
ret = SubRemLoadMapStateNotAllOK; ret = SubRemLoadMapStateNotAllOK;
@ -96,6 +86,9 @@ static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* f
FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]);
#endif #endif
sub_preset->type = SubGhzProtocolTypeUnknown; sub_preset->type = SubGhzProtocolTypeUnknown;
} else if(!path_contains_only_ascii(furi_string_get_cstr(sub_preset->file_path))) {
FURI_LOG_E(TAG, "Incorrect characters in [%s] file path", map_file_labels[i][0]);
sub_preset->type = SubGhzProtocolTypeUnknown;
} else if(!flipper_format_rewind(fff_data_file)) { } else if(!flipper_format_rewind(fff_data_file)) {
// Rewind error // Rewind error
} else if(!flipper_format_read_string( } else if(!flipper_format_read_string(
@ -103,8 +96,6 @@ static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* f
#if FURI_DEBUG #if FURI_DEBUG
FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]);
#endif #endif
// TODO move to remote scene
path_extract_filename(sub_preset->file_path, sub_preset->label, true);
ret = true; ret = true;
} else { } else {
ret = true; ret = true;
@ -237,17 +228,17 @@ bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset)
NULL, NULL,
0); 0);
#ifdef APP_SUBGHZREMOTE
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
keeloq_reset_original_btn(); keeloq_reset_original_btn();
subghz_custom_btns_reset(); subghz_custom_btns_reset();
#endif
if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) { if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) {
ret = true; ret = true;
} }
} }
app->tx_running = ret;
return ret; return ret;
} }
@ -256,22 +247,18 @@ bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) {
SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub];
if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) {
// XXX drop app->tx_running subghz_txrx_stop(app->txrx);
if(app->tx_running) { #ifdef APP_SUBGHZREMOTE
subghz_txrx_stop(app->txrx); if(sub_preset->type == SubGhzProtocolTypeDynamic) {
keeloq_reset_mfname();
if(sub_preset->type == SubGhzProtocolTypeDynamic) { keeloq_reset_kl_type();
keeloq_reset_mfname(); star_line_reset_mfname();
keeloq_reset_kl_type(); star_line_reset_kl_type();
keeloq_reset_original_btn();
subghz_custom_btns_reset();
star_line_reset_mfname();
star_line_reset_kl_type();
}
app->tx_running = false;
return true;
} }
keeloq_reset_original_btn();
subghz_custom_btns_reset();
#endif
return true;
} }
return false; return false;
@ -284,7 +271,7 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) {
SubRemLoadMapState ret = SubRemLoadMapStateBack; SubRemLoadMapState ret = SubRemLoadMapStateBack;
DialogsFileBrowserOptions browser_options; DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_sub1_10px); dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_subrem_10px);
browser_options.base_path = SUBREM_APP_FOLDER; browser_options.base_path = SUBREM_APP_FOLDER;
// Input events and views are managed by file_select // Input events and views are managed by file_select

View file

@ -2,34 +2,31 @@
#include "helpers/subrem_types.h" #include "helpers/subrem_types.h"
#include "helpers/subrem_presets.h" #include "helpers/subrem_presets.h"
#include "scenes/subrem_scene.h"
#include "../subghz/helpers/subghz_txrx.h" #include "helpers/txrx/subghz_txrx.h"
#ifdef APP_SUBGHZREMOTE
#include <assets_icons.h> #include <assets_icons.h>
#else
#include <subrem_remote_fap_icons.h>
#endif
#include "views/remote.h" #include "views/remote.h"
#include "scenes/subrem_scene.h"
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <gui/modules/submenu.h> #include <gui/modules/submenu.h>
#include <gui/modules/widget.h> #include <gui/modules/widget.h>
#include <notification/notification_messages.h>
#include <gui/modules/text_input.h> #include <gui/modules/text_input.h>
#include <dialogs/dialogs.h>
#include <storage/storage.h>
#include <gui/modules/popup.h> #include <gui/modules/popup.h>
#include <dialogs/dialogs.h>
#include <notification/notification_messages.h>
#include <storage/storage.h>
#include <flipper_format/flipper_format_i.h> #include <flipper_format/flipper_format_i.h>
#include <lib/subghz/protocols/raw.h>
#include <lib/subghz/subghz_setting.h>
#include <lib/subghz/receiver.h>
#include <lib/subghz/transmitter.h>
#define SUBREM_APP_FOLDER EXT_PATH("subghz_remote") #define SUBREM_APP_FOLDER EXT_PATH("subghz_remote")
#define SUBREM_MAX_LEN_NAME 64 #define SUBREM_MAX_LEN_NAME 64
@ -42,7 +39,6 @@ typedef struct {
Submenu* submenu; Submenu* submenu;
FuriString* file_path; FuriString* file_path;
// char file_name_tmp[SUBREM_MAX_LEN_NAME];
SubRemViewRemote* subrem_remote_view; SubRemViewRemote* subrem_remote_view;
@ -50,8 +46,6 @@ typedef struct {
SubGhzTxRx* txrx; SubGhzTxRx* txrx;
bool tx_running;
uint8_t chusen_sub; uint8_t chusen_sub;
} SubGhzRemoteApp; } SubGhzRemoteApp;

View file

@ -4,7 +4,11 @@
#include <input/input.h> #include <input/input.h>
#include <gui/elements.h> #include <gui/elements.h>
#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 12 #include <lib/toolbox/path.h>
#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 30
#define SUBREM_VIEW_REMOTE_LEFT_OFFSET 10
#define SUBREM_VIEW_REMOTE_RIGHT_OFFSET 22
struct SubRemViewRemote { struct SubRemViewRemote {
View* view; View* view;
@ -12,19 +16,8 @@ struct SubRemViewRemote {
void* context; void* context;
}; };
// TODO: model
typedef struct { typedef struct {
// FuriString* up_label; char* labels[SubRemSubKeyNameMaxCount];
// FuriString* down_label;
// FuriString* left_label;
// FuriString* right_label;
// FuriString* ok_label;
char* up_label;
char* down_label;
char* left_label;
char* right_label;
char* ok_label;
SubRemViewRemoteState state; SubRemViewRemoteState state;
@ -41,26 +34,61 @@ void subrem_view_remote_set_callback(
subrem_view_remote->context = context; subrem_view_remote->context = context;
} }
void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels) { void subrem_view_remote_update_data_labels(
SubRemViewRemote* subrem_view_remote,
SubRemSubFilePreset** subs_presets) {
furi_assert(subrem_view_remote); furi_assert(subrem_view_remote);
furi_assert(subs_presets);
FuriString* labels[SubRemSubKeyNameMaxCount];
SubRemSubFilePreset* sub_preset;
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
sub_preset = subs_presets[i];
switch(sub_preset->load_state) {
case SubRemLoadSubStateOK:
if(!furi_string_empty(sub_preset->label)) {
labels[i] = furi_string_alloc_set(sub_preset->label);
} else if(!furi_string_empty(sub_preset->file_path)) {
labels[i] = furi_string_alloc();
path_extract_filename(sub_preset->file_path, labels[i], true);
} else {
labels[i] = furi_string_alloc_set("Empty Label");
}
break;
case SubRemLoadSubStateErrorNoFile:
labels[i] = furi_string_alloc_set("[X] Can't open file");
break;
case SubRemLoadSubStateErrorFreq:
case SubRemLoadSubStateErrorMod:
case SubRemLoadSubStateErrorProtocol:
labels[i] = furi_string_alloc_set("[X] Error in .sub file");
break;
default:
labels[i] = furi_string_alloc_set("");
break;
}
}
with_view_model( with_view_model(
subrem_view_remote->view, subrem_view_remote->view,
SubRemViewRemoteModel * model, SubRemViewRemoteModel * model,
{ {
strncpy(model->up_label, labels[0], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
strncpy(model->down_label, labels[1], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); strncpy(
strncpy(model->left_label, labels[2], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); model->labels[i],
strncpy(model->right_label, labels[3], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); furi_string_get_cstr(labels[i]),
strncpy(model->ok_label, labels[4], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
}
// furi_string_set(model->up_label, up_label);
// furi_string_set(model->down_label, down_label);
// furi_string_set(model->left_label, left_label);
// furi_string_set(model->right_label, right_label);
// furi_string_set(model->ok_label, ok_label);
}, },
true); true);
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
furi_string_free(labels[i]);
}
} }
void subrem_view_remote_set_state( void subrem_view_remote_set_state(
@ -95,24 +123,32 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) {
//Labels //Labels
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 10, 10, model->up_label); uint8_t y = 0;
canvas_draw_str(canvas, 10, 20, model->down_label); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
canvas_draw_str(canvas, 10, 30, model->left_label); elements_text_box(
canvas_draw_str(canvas, 10, 40, model->right_label); canvas,
canvas_draw_str(canvas, 10, 50, model->ok_label); SUBREM_VIEW_REMOTE_LEFT_OFFSET,
y + 2,
126 - SUBREM_VIEW_REMOTE_LEFT_OFFSET - SUBREM_VIEW_REMOTE_RIGHT_OFFSET,
12,
AlignLeft,
AlignBottom,
model->labels[i],
false);
y += 10;
}
// canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); if(model->state == SubRemViewRemoteStateOFF) {
// canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); elements_button_left(canvas, "Back");
// canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); elements_button_right(canvas, "Save");
// canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); } else {
// canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit.");
}
canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit.");
//Status text and indicator //Status text and indicator
canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13);
if(model->state == SubRemViewRemoteStateIdle) { if(model->state == SubRemViewRemoteStateIdle || model->state == SubRemViewRemoteStateOFF) {
canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle");
} else { } else {
switch(model->state) { switch(model->state) {
@ -147,10 +183,6 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) {
break; break;
} }
} }
//Repeat indicator
//canvas_draw_str_aligned(canvas, 125, 40, AlignRight, AlignBottom, "Repeat:");
//canvas_draw_icon(canvas, 115, 39, &I_SubGHzRemote_Repeat_12x14);
//canvas_draw_str_aligned(canvas, 125, 62, AlignRight, AlignBottom, int_to_char(app->repeat));
} }
bool subrem_view_remote_input(InputEvent* event, void* context) { bool subrem_view_remote_input(InputEvent* event, void* context) {
@ -158,17 +190,6 @@ bool subrem_view_remote_input(InputEvent* event, void* context) {
SubRemViewRemote* subrem_view_remote = context; SubRemViewRemote* subrem_view_remote = context;
if(event->key == InputKeyBack && event->type == InputTypeLong) { if(event->key == InputKeyBack && event->type == InputTypeLong) {
with_view_model(
subrem_view_remote->view,
SubRemViewRemoteModel * model,
{
strcpy(model->up_label, "N/A");
strcpy(model->down_label, "N/A");
strcpy(model->left_label, "N/A");
strcpy(model->right_label, "N/A");
strcpy(model->ok_label, "N/A");
},
false);
subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context); subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context);
return true; return true;
} else if(event->key == InputKeyBack && event->type == InputTypeShort) { } else if(event->key == InputKeyBack && event->type == InputTypeShort) {
@ -240,23 +261,10 @@ SubRemViewRemote* subrem_view_remote_alloc() {
{ {
model->state = SubRemViewRemoteStateIdle; model->state = SubRemViewRemoteStateIdle;
model->up_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
model->down_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); model->labels[i] = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1);
model->left_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); strcpy(model->labels[i], "");
model->right_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); }
model->ok_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1);
strcpy(model->up_label, "N/A");
strcpy(model->down_label, "N/A");
strcpy(model->left_label, "N/A");
strcpy(model->right_label, "N/A");
strcpy(model->ok_label, "N/A");
// model->up_label = furi_string_alloc_set_str("N/A");
// model->down_label = furi_string_alloc_set_str("N/A");
// model->left_label = furi_string_alloc_set_str("N/A");
// model->right_label = furi_string_alloc_set_str("N/A");
// model->ok_label = furi_string_alloc_set_str("N/A");
model->pressed_btn = 0; model->pressed_btn = 0;
}, },
@ -271,17 +279,9 @@ void subrem_view_remote_free(SubRemViewRemote* subghz_remote) {
subghz_remote->view, subghz_remote->view,
SubRemViewRemoteModel * model, SubRemViewRemoteModel * model,
{ {
free(model->up_label); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
free(model->down_label); free(model->labels[i]);
free(model->left_label); }
free(model->right_label);
free(model->ok_label);
// furi_string_free(model->up_label);
// furi_string_free(model->down_label);
// furi_string_free(model->left_label);
// furi_string_free(model->right_label);
// furi_string_free(model->ok_label);
}, },
true); true);
view_free(subghz_remote->view); view_free(subghz_remote->view);

View file

@ -2,11 +2,13 @@
#include <gui/view.h> #include <gui/view.h>
#include "../helpers/subrem_custom_event.h" #include "../helpers/subrem_custom_event.h"
#include "../helpers/subrem_presets.h"
typedef enum { typedef enum {
SubRemViewRemoteStateIdle, SubRemViewRemoteStateIdle,
SubRemViewRemoteStateLoading, SubRemViewRemoteStateLoading,
SubRemViewRemoteStateSending, SubRemViewRemoteStateSending,
SubRemViewRemoteStateOFF,
} SubRemViewRemoteState; } SubRemViewRemoteState;
typedef struct SubRemViewRemote SubRemViewRemote; typedef struct SubRemViewRemote SubRemViewRemote;
@ -24,7 +26,9 @@ void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote);
View* subrem_view_remote_get_view(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** labels); void subrem_view_remote_update_data_labels(
SubRemViewRemote* subrem_view_remote,
SubRemSubFilePreset** subs_presets);
void subrem_view_remote_set_state( void subrem_view_remote_set_state(
SubRemViewRemote* subrem_view_remote, SubRemViewRemote* subrem_view_remote,

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB