Просмотр исходного кода

Merge pull request #14 from leedave/feature/subghz_encoded

Feature/subghz encoded
David Lee 1 год назад
Родитель
Сommit
4d4962f68b

+ 9 - 2
README.md

@@ -30,9 +30,16 @@ Wouldn't it be nicer to simply click one button and let everything happen? This
 - Add pauses, becaue target systems are not always fast enough for multiple commands<br>
 - Run file containing chained IR & SubGhz commands<br>
 
+### Settings
+- LED FX, allow the LED to blink
+- Save settings, stores a file with your settings in it on exit
+- IR time ms, the default duration of an IR signal transmission. Individual times can be set
+- SubG. time ms, the default duration of a SubGhz signal. Only needed for Encoded signals, RAW files play until finished
+
 ### Limitations
-SubGhz commands will stop working if you move/rename/delete the original files on your Flipper. This is because 
-of how the Flippers SubGhz worker expects data. 
+SubGhz commands will stop working if you move/rename/delete the original files on your Flipper. This is because of how the Flippers SubGhz worker expects data. 
+
+After an upgrade a crash on exit can occur, due to small improvements to the file formats. Sorry about that, it only happens once. 
 
 ## How to install on Flipper Zero
 - If you do not have one, download a firmware<br>

+ 1 - 1
application.fam

@@ -6,7 +6,7 @@ App(
     stack_size=3 * 1024,
     fap_icon="icons/xremote_10px.png",
     fap_icon_assets="icons",
-    fap_version="2.3",
+    fap_version="2.4",
     fap_category="Infrared",
     fap_author="Leedave",
     fap_description="One-Click, sends multiple commands",

+ 1 - 0
docs/README.md

@@ -10,6 +10,7 @@ This app combines your IR and SubGhz commands into a playlist that can be run wi
 - Save your command chain / playlist to flipper
 - Disable LED effects if not wanted
 - Configure duration of IR Signals
+- Configure default duration of Encoded SubGhz Signals
 
 ## What good is this?
 

+ 6 - 0
docs/changelog.md

@@ -1,3 +1,9 @@
+## 2.4
+- Added support for encoded SubGhz files
+- Added timer for SubGhz transmission (not needed in RAW files)
+- Added version number to app info screen
+- Minor updates/instrutions in readme.md
+
 ## 2.3
 - Fixed Crash after creating chains with SubGhz Items
 

+ 28 - 10
helpers/subghz/subghz.c

@@ -9,6 +9,7 @@ SubGhz* subghz_alloc() {
 
     subghz->file_path = furi_string_alloc();
     subghz->txrx = subghz_txrx_alloc();
+    subghz->dialogs = furi_record_open(RECORD_DIALOGS);
 
     return subghz;
 }
@@ -16,6 +17,7 @@ SubGhz* subghz_alloc() {
 void subghz_free(SubGhz* subghz) {
     subghz_txrx_free(subghz->txrx);
     furi_string_free(subghz->file_path);
+    furi_record_close(RECORD_DIALOGS);
 
     // The rest
     free(subghz);
@@ -38,16 +40,32 @@ void subghz_scene_transmit_callback_end_tx(void* context) {
 void subghz_send(void* context, const char* path) {
     XRemote* app = context;
 
-    subghz_load_protocol_from_file(app->subghz, path);
-    FURI_LOG_D(TAG, "Starting Transmission");
-    subghz_txrx_tx_start(
-        app->subghz->txrx,
-        subghz_txrx_get_fff_data(app->subghz->txrx)); //Seems like it must be done this way
+    if(!subghz_load_protocol_from_file(app->subghz, path)) {
+        xremote_cross_remote_set_transmitting(app->cross_remote, XRemoteTransmittingStop);
+        app->transmitting = false;
+        return;
+    }
 
-    FURI_LOG_D(TAG, "setting sugbhz raw file encoder worker callback");
-    subghz_txrx_set_raw_file_encoder_worker_callback_end(
-        app->subghz->txrx, subghz_scene_transmit_callback_end_tx, app);
-    app->state_notifications = SubGhzNotificationStateTx;
+    if(subghz_get_load_type_file(app->subghz) == SubGhzLoadTypeFileRaw) {
+        FURI_LOG_D(TAG, "Starting Transmission");
+        subghz_txrx_tx_start(
+            app->subghz->txrx,
+            subghz_txrx_get_fff_data(app->subghz->txrx)); //Seems like it must be done this way
 
-    FURI_LOG_D(TAG, "Finished Transmitting");
+        FURI_LOG_D(TAG, "setting sugbhz raw file encoder worker callback");
+        subghz_txrx_set_raw_file_encoder_worker_callback_end(
+            app->subghz->txrx, subghz_scene_transmit_callback_end_tx, app);
+        app->state_notifications = SubGhzNotificationStateTx;
+
+        FURI_LOG_D(TAG, "Finished Transmitting");
+    } else {
+        subghz_tx_start(app->subghz, subghz_txrx_get_fff_data(app->subghz->txrx));
+        app->state_notifications = SubGhzNotificationStateTx;
+        furi_thread_flags_wait(0, FuriFlagWaitAny, app->sg_timing);
+        app->state_notifications = SubGhzNotificationStateIDLE;
+        subghz_txrx_stop(app->subghz->txrx);
+
+        xremote_cross_remote_set_transmitting(app->cross_remote, XRemoteTransmittingStop);
+        app->transmitting = false;
+    }
 }

+ 5 - 22
helpers/subghz/subghz_i.c

@@ -26,14 +26,14 @@ void subghz_set_default_preset(SubGhz* subghz) {
         0);
 }*/
 
-/*bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
+bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
     switch(subghz_txrx_tx_start(subghz->txrx, flipper_format)) {
     case SubGhzTxRxStartTxStateErrorParserOthers:
         dialog_message_show_storage_error(
             subghz->dialogs, "Error in protocol\nparameters\ndescription");
         break;
     case SubGhzTxRxStartTxStateErrorOnlyRx:
-        FURI_LOG_D(TAG, 'Cannot send, only RX possible');
+        // FURI_LOG_D(TAG, 'Cannot send, only RX possible');
         break;
 
     default:
@@ -41,7 +41,7 @@ void subghz_set_default_preset(SubGhz* subghz) {
         break;
     }
     return false;
-}*/
+}
 
 bool subghz_key_load(SubGhz* subghz, const char* file_path) { //, bool show_dialog) {
     furi_assert(subghz);
@@ -182,34 +182,17 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { //, bool show_dial
     return false;
 }
 
-/*SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz) {
+SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz) {
     furi_assert(subghz);
     return subghz->load_type_file;
-}*/
+}
 
 bool subghz_load_protocol_from_file(SubGhz* subghz, const char* path) {
     furi_assert(subghz);
 
-    //FuriString* file_path = furi_string_alloc();
-
     bool res = false;
 
-    /*DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(
-        &browser_options, SUBGHZ_APP_FILENAME_EXTENSION, &I_sub1_10px);
-    browser_options.base_path = SUBGHZ_APP_FOLDER;
-
-    // Input events and views are managed by file_select
-    bool res = dialog_file_browser_show(
-        subghz->dialogs, subghz->file_path, subghz->file_path, &browser_options);
-
-    if(res) {*/
-    //res = subghz_key_load(subghz, furi_string_get_cstr(subghz->file_path), true);
     res = subghz_key_load(subghz, path); //, true);
-    //}
-
-    //furi_string_free(file_path);
-
     return res;
 }
 

+ 4 - 2
helpers/subghz/subghz_i.h

@@ -43,6 +43,7 @@ typedef struct SubGhz SubGhz;
 struct SubGhz {
     SubGhzTxRx* txrx;
     FuriString* file_path;
+    DialogsApp* dialogs;
     //FuriString* file_path_tmp;
     //char file_name_tmp[SUBGHZ_MAX_LEN_NAME]; // just left it in to make the object not empty
     //SubGhzNotificationState state_notifications;
@@ -67,13 +68,14 @@ struct SubGhz {
 //void subghz_blink_start(SubGhz* subghz);
 //void subghz_blink_stop(SubGhz* subghz);
 
-//bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
+// Used on Encoded SubGhz
+bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format);
 //void subghz_dialog_message_show_only_rx(SubGhz* subghz);
 
 bool subghz_key_load(SubGhz* subghz, const char* file_path); //, bool show_dialog);
 bool subghz_load_protocol_from_file(SubGhz* subghz, const char* path);
 //bool subghz_file_available(SubGhz* subghz);
-//SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz);
+SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz);
 
 //void subghz_lock(SubGhz* subghz);
 //void subghz_unlock(SubGhz* subghz);

+ 2 - 0
helpers/xremote_storage.c

@@ -58,6 +58,7 @@ void xremote_save_settings(void* context) {
     flipper_format_write_uint32(
         fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
     flipper_format_write_uint32(fff_file, XREMOTE_SETTINGS_KEY_IR_TIMING, &app->ir_timing, 1);
+    flipper_format_write_uint32(fff_file, XREMOTE_SETTINGS_KEY_SG_TIMING, &app->sg_timing, 1);
 
     if(!flipper_format_rewind(fff_file)) {
         xremote_close_config_file(fff_file);
@@ -110,6 +111,7 @@ void xremote_read_settings(void* context) {
     flipper_format_read_uint32(
         fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
     flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_IR_TIMING, &app->ir_timing, 1);
+    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_SG_TIMING, &app->sg_timing, 1);
 
     flipper_format_rewind(fff_file);
 

+ 1 - 0
helpers/xremote_storage.h

@@ -12,6 +12,7 @@
 #define XREMOTE_SETTINGS_KEY_SPEAKER "Speaker"
 #define XREMOTE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings"
 #define XREMOTE_SETTINGS_KEY_IR_TIMING "IRTiming"
+#define XREMOTE_SETTINGS_KEY_SG_TIMING "SGTiming"
 
 void xremote_save_settings(void* context);
 void xremote_read_settings(void* context);

+ 18 - 1
scenes/xremote_scene_settings.c

@@ -81,6 +81,15 @@ static void xremote_scene_settings_set_ir_timing(VariableItem* item) {
     app->ir_timing = (index * 100);
 }
 
+static void xremote_scene_settings_set_sg_timing(VariableItem* item) {
+    XRemote* app = variable_item_get_context(item);
+    uint32_t index = variable_item_get_current_value_index(item);
+
+    snprintf(app->sg_timing_char, 20, "%lu", (index * 100));
+    variable_item_set_current_value_text(item, app->sg_timing_char);
+    app->sg_timing = (index * 100);
+}
+
 void xremote_scene_settings_submenu_callback(void* context, uint32_t index) {
     XRemote* app = context;
     view_dispatcher_send_custom_event(app->view_dispatcher, index);
@@ -121,12 +130,20 @@ void xremote_scene_settings_on_enter(void* context) {
 
     // Set Infrared Timer
     item = variable_item_list_add(
-        app->variable_item_list, "IR Timing in ms:", 30, xremote_scene_settings_set_ir_timing, app);
+        app->variable_item_list, "IR Time ms", 30, xremote_scene_settings_set_ir_timing, app);
 
     variable_item_set_current_value_index(item, (uint8_t)(app->ir_timing / 100));
     snprintf(app->ir_timing_char, 20, "%lu", app->ir_timing);
     variable_item_set_current_value_text(item, app->ir_timing_char);
 
+    // Set SubGhz Timer
+    item = variable_item_list_add(
+        app->variable_item_list, "SubG. Time ms", 30, xremote_scene_settings_set_sg_timing, app);
+
+    variable_item_set_current_value_index(item, (uint8_t)(app->sg_timing / 100));
+    snprintf(app->sg_timing_char, 20, "%lu", app->sg_timing);
+    variable_item_set_current_value_text(item, app->sg_timing_char);
+
     view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdSettings);
 }
 

+ 4 - 0
views/xremote_infoscreen.c

@@ -23,6 +23,7 @@ void xremote_infoscreen_set_callback(
 
 void xremote_infoscreen_draw(Canvas* canvas, XRemoteInfoscreenModel* model) {
     UNUSED(model);
+    char buffer[64];
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
     canvas_set_font(canvas, FontPrimary);
@@ -30,6 +31,9 @@ void xremote_infoscreen_draw(Canvas* canvas, XRemoteInfoscreenModel* model) {
     canvas_set_font(canvas, FontSecondary);
     canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Chain IR and SubGhz");
     canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "Commands");
+
+    snprintf(buffer, sizeof(buffer), "Version: %s", XREMOTE_VERSION);
+    canvas_draw_str_aligned(canvas, 64, 42, AlignCenter, AlignTop, buffer);
     elements_button_center(canvas, "Back");
 }
 

+ 2 - 0
xremote.c

@@ -49,6 +49,8 @@ XRemote* xremote_app_alloc() {
     app->transmitting = 0;
     app->ir_timing = 1000;
     app->ir_timing_char = "1000";
+    app->sg_timing = 500;
+    app->sg_timing_char = "500";
     app->stop_transmit = false;
 
     // Load configs

+ 2 - 0
xremote.h

@@ -46,6 +46,8 @@ typedef struct {
     uint32_t edit_item;
     uint32_t ir_timing;
     char* ir_timing_char;
+    uint32_t sg_timing;
+    char* sg_timing_char;
     bool transmitting;
     bool stop_transmit;
     char text_store[XREMOTE_TEXT_STORE_NUM][XREMOTE_TEXT_STORE_SIZE + 1];

+ 1 - 0
xremote_i.h

@@ -53,6 +53,7 @@
 #define XREMOTE_TEXT_STORE_SIZE 128
 #define XREMOTE_MAX_ITEM_NAME_LENGTH 22
 #define XREMOTE_MAX_REMOTE_NAME_LENGTH 22
+#define XREMOTE_VERSION "2.4"
 
 #define INFRARED_APP_EXTENSION ".ir"
 #define INFRARED_APP_FOLDER ANY_PATH("infrared")