Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subghz_remote_app #477

Merged
merged 5 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions applications/main/subghz_remote/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ App(
name="Sub-GHz Remote",
apptype=FlipperAppType.APP,
entry_point="subghz_remote_app",
cdefines=["APP_SUBGHZREMOTE"],
cdefines=[
"APP_SUBGHZREMOTE",
"SUBREM_LIGHT",
],
requires=[
"gui",
"dialogs",
],
icon="A_SubGHzRemote_14",
stack_size=4 * 1024,
order=11,
)
)
18 changes: 18 additions & 0 deletions applications/main/subghz_remote/helpers/subrem_custom_event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

typedef enum {
//SubmenuIndex
SubmenuIndexSubRemOpenMapFile,
SubmenuIndexSubRemRemoteView,
SubmenuIndexSubRemAbout,

//SubRemCustomEvent
SubRemCustomEventViewRemoteStartUP = 100,
SubRemCustomEventViewRemoteStartDOWN,
SubRemCustomEventViewRemoteStartLEFT,
SubRemCustomEventViewRemoteStartRIGHT,
SubRemCustomEventViewRemoteStartOK,
SubRemCustomEventViewRemoteBack,
SubRemCustomEventViewRemoteStop,
SubRemCustomEventViewRemoteForcedStop,
} SubRemCustomEvent;
32 changes: 32 additions & 0 deletions applications/main/subghz_remote/helpers/subrem_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include <furi.h>
#include <furi_hal.h>

// TODO: File version/type logic
// #define SUBREM_APP_APP_FILE_VERSION 1
// #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file"
#define SUBREM_APP_EXTENSION ".txt"

typedef enum {
SubRemSubKeyNameUp = (0U),
SubRemSubKeyNameDown,
SubRemSubKeyNameLeft,
SubRemSubKeyNameRight,
SubRemSubKeyNameOk,
SubRemSubKeyNameMaxCount,
} SubRemSubKeyName;

typedef enum {
SubRemViewSubmenu,
SubRemViewWidget,
SubRemViewPopup,
SubRemViewTextInput,
SubRemViewIDRemote,
} SubRemViewID;

typedef enum {
SubRemLoadMapStateBack = 0,
SubRemLoadMapStateError,
SubRemLoadMapStateOK,
} SubRemLoadMapState;
30 changes: 30 additions & 0 deletions applications/main/subghz_remote/scenes/subrem_scene.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../subghz_remote_app_i.h"

// Generate scene on_enter handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
void (*const subrem_scene_on_enter_handlers[])(void*) = {
#include "subrem_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_event handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
bool (*const subrem_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
#include "subrem_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_exit handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
void (*const subrem_scene_on_exit_handlers[])(void* context) = {
#include "subrem_scene_config.h"
};
#undef ADD_SCENE

// Initialize scene handlers configuration structure
const SceneManagerHandlers subrem_scene_handlers = {
.on_enter_handlers = subrem_scene_on_enter_handlers,
.on_event_handlers = subrem_scene_on_event_handlers,
.on_exit_handlers = subrem_scene_on_exit_handlers,
.scene_num = SubRemSceneNum,
};
29 changes: 29 additions & 0 deletions applications/main/subghz_remote/scenes/subrem_scene.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <gui/scene_manager.h>

// Generate scene id and total number
#define ADD_SCENE(prefix, name, id) SubRemScene##id,
typedef enum {
#include "subrem_scene_config.h"
SubRemSceneNum,
} SubRemScene;
#undef ADD_SCENE

extern const SceneManagerHandlers subrem_scene_handlers;

// Generate scene on_enter handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
#include "subrem_scene_config.h"
#undef ADD_SCENE

// Generate scene on_event handlers declaration
#define ADD_SCENE(prefix, name, id) \
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
#include "subrem_scene_config.h"
#undef ADD_SCENE

// Generate scene on_exit handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
#include "subrem_scene_config.h"
#undef ADD_SCENE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ADD_SCENE(subrem, start, Start)
ADD_SCENE(subrem, openmapfile, OpenMapFile)
ADD_SCENE(subrem, remote, Remote)
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#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 == SubRemLoadMapStateError) {
#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) {
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);
}
130 changes: 130 additions & 0 deletions applications/main/subghz_remote/scenes/subrem_scene_remote.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "../subghz_remote_app_i.h"
#include "../views/remote.h"

#include <lib/subghz/protocols/raw.h>

#define TAG "SubRemScenRemote"

void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) {
furi_assert(context);
SubGhzRemoteApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, event);
}

void subrem_scene_remote_raw_callback_end_tx(void* context) {
furi_assert(context);
SubGhzRemoteApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewRemoteForcedStop);
}

static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) {
uint8_t ret = 0;

if(event_id == SubRemCustomEventViewRemoteStartUP) {
ret = SubRemSubKeyNameUp;
} else if(event_id == SubRemCustomEventViewRemoteStartDOWN) {
ret = SubRemSubKeyNameDown;
} else if(event_id == SubRemCustomEventViewRemoteStartLEFT) {
ret = SubRemSubKeyNameLeft;
} else if(event_id == SubRemCustomEventViewRemoteStartRIGHT) {
ret = SubRemSubKeyNameRight;
} else if(event_id == SubRemCustomEventViewRemoteStartOK) {
ret = SubRemSubKeyNameOk;
}

return ret;
}

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->subs_preset[0]->label),
furi_string_get_cstr(app->subs_preset[1]->label),
furi_string_get_cstr(app->subs_preset[2]->label),
furi_string_get_cstr(app->subs_preset[3]->label),
furi_string_get_cstr(app->subs_preset[4]->label));

return ret;
}

void subrem_scene_remote_on_enter(void* context) {
SubGhzRemoteApp* app = context;

subrem_scene_remote_update_data_show(app);

subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app);

view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDRemote);
}

bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) {
SubGhzRemoteApp* app = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubRemCustomEventViewRemoteBack) {
if(!scene_manager_search_and_switch_to_previous_scene(
app->scene_manager, SubRemSceneOpenMapFile)) {
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);
}
}
return true;
} else if(
event.event == SubRemCustomEventViewRemoteStartUP ||
event.event == SubRemCustomEventViewRemoteStartDOWN ||
event.event == SubRemCustomEventViewRemoteStartLEFT ||
event.event == SubRemCustomEventViewRemoteStartRIGHT ||
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->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);
subrem_view_remote_set_state(
app->subrem_remote_view, SubRemViewRemoteStateSending);
notification_message(app->notifications, &sequence_blink_start_magenta);
} else {
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
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);

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);

notification_message(app->notifications, &sequence_blink_stop);
}
return true;
}
}
// } else if(event.type == SceneManagerEventTypeTick) {
// }
return false;
}

void subrem_scene_remote_on_exit(void* context) {
SubGhzRemoteApp* app = 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);

notification_message(app->notifications, &sequence_blink_stop);
}
74 changes: 74 additions & 0 deletions applications/main/subghz_remote/scenes/subrem_scene_start.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "../subghz_remote_app_i.h"
#include "../helpers/subrem_custom_event.h"

void subrem_scene_start_submenu_callback(void* context, uint32_t index) {
furi_assert(context);
SubGhzRemoteApp* app = context;

view_dispatcher_send_custom_event(app->view_dispatcher, index);
}

void subrem_scene_start_on_enter(void* context) {
furi_assert(context);

SubGhzRemoteApp* app = context;
Submenu* submenu = app->submenu;
submenu_add_item(
submenu,
"Open Map File",
SubmenuIndexSubRemOpenMapFile,
subrem_scene_start_submenu_callback,
app);
#if FURI_DEBUG
submenu_add_item(
submenu,
"Remote_Debug",
SubmenuIndexSubRemRemoteView,
subrem_scene_start_submenu_callback,
app);
#endif
// submenu_add_item(
// submenu,
// "About",
// SubmenuIndexSubGhzRemoteAbout,
// subrem_scene_start_submenu_callback,
// app);

submenu_set_selected_item(
submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart));

view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu);
}

bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) {
furi_assert(context);

SubGhzRemoteApp* app = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSubRemOpenMapFile) {
scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile);
consumed = true;
}
// } else if(event.event == SubmenuIndexSubRemAbout) {
// scene_manager_next_scene(app->scene_manager, SubRemSceneAbout);
// consumed = true;
// }
#if FURI_DEBUG
else if(event.event == SubmenuIndexSubRemRemoteView) {
scene_manager_next_scene(app->scene_manager, SubRemSceneRemote);
consumed = true;
}
#endif
}

return consumed;
}

void subrem_scene_start_on_exit(void* context) {
furi_assert(context);

SubGhzRemoteApp* app = context;
submenu_reset(app->submenu);
}
Loading