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

Added animations, refactored transmission for interruption option

David Lee 1 год назад
Родитель
Сommit
afbe4c41be

+ 6 - 0
README.md

@@ -29,6 +29,7 @@ Wouldn't it be nicer to simply click one button and let everything happen? This
 - Save chained commands to a file<br>
 - Add pauses, becaue target systems are not always fast enough for multiple commands<br>
 - Run file containing chained IR & SubGhz commands<br>
+- Loop Transmissions until quit
 
 ### Settings
 - LED FX, allow the LED to blink
@@ -52,5 +53,10 @@ Then run the command:
  ```
 The application will be compiled and copied onto your device. 
 
+## Thank you notes
+- [Willy-JL](https://github.com/Willy-JL) for distributing in Momentum Firmware
+- [Roguemaster](https://github.com/RogueMaster/flipperzero-firmware-wPlugins) for distributing in Roguemaster Firmware
+- [Miccayo](https://github.com/miccayo) for contributing the loop transmit feature
+
 ## Licensing
 This code is open-source and may be used for whatever you want to do with it. 

+ 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.8",
+    fap_version="3.0",
     fap_category="Infrared",
     fap_author="Leedave",
     fap_description="One-Click, sends multiple commands",

+ 1 - 0
docs/README.md

@@ -11,6 +11,7 @@ This app combines your IR and SubGhz commands into a playlist that can be run wi
 - Disable LED effects if not wanted
 - Configure duration of IR Signals
 - Configure default duration of Encoded SubGhz Signals
+- Loop Transmissions until quit
 
 ## What good is this?
 

+ 5 - 0
docs/changelog.md

@@ -1,3 +1,8 @@
+## 3.0
+- Added loop transmit feature (thanks to miccayo)
+- Replaced transmission counter with animations
+- Refactored the transmission part to allow interruption of command chains
+
 ## 2.8
 - Update SubGhz Protocoll to include flippers official rolling code support
 

BIN
icons/KeyBackspaceSelected_16x9.png


BIN
icons/KeyBackspace_16x9.png


BIN
icons/KeySaveSelected_24x11.png


BIN
icons/KeySave_24x11.png


BIN
icons/ir_ani_1_32x22.png


BIN
icons/ir_ani_2_32x22.png


BIN
icons/ir_ani_32x22.png


BIN
icons/ir_ani_3_32x22.png


BIN
icons/pause_ani_1_22x23.png


BIN
icons/pause_ani_2_22x23.png


BIN
icons/pause_ani_3_22x23.png


BIN
icons/sg_ani_1_19x13.png


BIN
icons/sg_ani_2_19x13.png


BIN
icons/sg_ani_3_19x13.png


+ 43 - 49
scenes/xremote_scene_transmit.c

@@ -18,9 +18,10 @@ static const NotificationSequence* xremote_notification_sequences[] = {
     &sequence_blink_stop,
 };
 
-void xremote_transmit_callback(XRemoteCustomEvent event, void* context) {
+void xremote_scene_transmit_callback(XRemoteCustomEvent event, void* context) {
     furi_assert(context);
     XRemote* app = context;
+    FURI_LOG_D(TAG, "trigger xremote_transmit_callback");
     view_dispatcher_send_custom_event(app->view_dispatcher, event);
 }
 
@@ -114,80 +115,69 @@ void xremote_scene_transmit_send_signal(void* context, CrossRemoteItem* item) {
     }
 }
 
-void xremote_scene_transmit_run_remote(void* context) {
-    furi_assert(context);
-    XRemote* app = context;
+static void xremote_scene_transmit_end_scene(XRemote* app) {
+    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
+    scene_manager_previous_scene(app->scene_manager);
+}
+
+static void xremote_scene_transmit_run_single_transmit(XRemote* app) {
     CrossRemote* remote = app->cross_remote;
+    if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingIdle) {
+        xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingStart);
+        CrossRemoteItem* item = xremote_cross_remote_get_item(remote, app->transmit_item);
+        xremote_scene_transmit_send_signal(app, item);
+    } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStopSubghz) {
+        app->transmit_item++;
+        app->state_notifications = SubGhzNotificationStateIDLE;
+        app->transmitting = false;
+        subghz_txrx_stop(app->subghz->txrx);
+        xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStop);
+        xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
+    } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStop) {
+        app->transmit_item++;
+        xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
+    }
+}
 
+static void xremote_scene_transmit_run_next_transmission(XRemote* app) {
+    CrossRemote* remote = app->cross_remote;
     size_t item_count = xremote_cross_remote_get_item_count(remote);
-    if (app->loop_transmit) {
-        while (true) {
-            for (size_t i = 0; i < item_count;) {
-                if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingIdle) {
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingStart);
-                    CrossRemoteItem* item = xremote_cross_remote_get_item(remote, i);
-                    xremote_scene_transmit_send_signal(app, item);
-                } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStopSubghz) {
-                    i++;
-                    app->state_notifications = SubGhzNotificationStateIDLE;
-                    app->transmitting = false;
-                    subghz_txrx_stop(app->subghz->txrx);
-                    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStop);
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
-                } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStop) {
-                    i++;
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
-                }
-            }
-        }
-    } else {
-        for (size_t i = 0; i < item_count;) {
-                if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingIdle) {
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingStart);
-                    CrossRemoteItem* item = xremote_cross_remote_get_item(remote, i);
-                    xremote_scene_transmit_send_signal(app, item);
-                } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStopSubghz) {
-                    i++;
-                    app->state_notifications = SubGhzNotificationStateIDLE;
-                    app->transmitting = false;
-                    subghz_txrx_stop(app->subghz->txrx);
-                    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStop);
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
-                } else if (xremote_cross_remote_get_transmitting(remote) == XRemoteTransmittingStop) {
-                    i++;
-                    xremote_cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
-                }
-            }
+    if (app->transmit_item < item_count) {
+        xremote_scene_transmit_run_single_transmit(app);
+        return;
     }
-    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
-
-    scene_manager_previous_scene(app->scene_manager);
+    if (app->loop_transmit && !app->stop_transmit) {
+        app->transmit_item = 0;
+        return;
+    }
+    xremote_scene_transmit_end_scene(app);
 }
 
 void xremote_scene_transmit_on_enter(void* context) {
     furi_assert(context);
     XRemote* app = context;
-    xremote_transmit_set_callback(app->xremote_transmit, xremote_transmit_callback, app);
+    app->transmit_item = 0;
+    xremote_transmit_set_callback(app->xremote_transmit, xremote_scene_transmit_callback, app);
 
     view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTransmit);
-    xremote_scene_transmit_run_remote(app);
 }
 
 bool xremote_scene_transmit_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-
+    
     if(event.type == SceneManagerEventTypeCustom) {
         FURI_LOG_D(TAG, "Custom Event");
         switch(event.event) {
         case XRemoteCustomEventViewTransmitterSendStop:
-            FURI_LOG_D("SUBGHZ", "stop event"); // doesn't trigger
+            app->stop_transmit = true;
             break;
         default:
             break;
         }
     } else if(event.type == SceneManagerEventTypeTick) {
         FURI_LOG_D(TAG, "Tick Event");
+        xremote_scene_transmit_run_next_transmission(app);
         with_view_model(
             xremote_transmit_get_view(app->xremote_transmit),
             void* model,
@@ -196,6 +186,10 @@ bool xremote_scene_transmit_on_event(void* context, SceneManagerEvent event) {
         if(app->state_notifications == SubGhzNotificationStateTx && app->led == 1) {
             //blink for subghz
         }
+        if(app->stop_transmit == true) {
+            app->stop_transmit = false;
+            xremote_scene_transmit_end_scene(app);
+        }
     }
 
     return consumed;

+ 46 - 29
views/xremote_transmit.c

@@ -50,12 +50,16 @@ void xremote_transmit_draw_ir(Canvas* canvas, XRemoteTransmitModel* model) {
     canvas_set_font(canvas, FontPrimary);
     canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending");
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Infrared");
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+    canvas_draw_str_aligned(canvas, 74, 15, AlignLeft, AlignTop, "Infrared");
+    canvas_draw_str_aligned(canvas, 74, 25, AlignLeft, AlignTop, model->name);
+
+    if (model->time == 0) {
+        canvas_draw_icon(canvas, 36, 2, &I_ir_ani_1_32x22);
+    } else if (model->time == 1) {
+        canvas_draw_icon(canvas, 36, 2, &I_ir_ani_2_32x22);
+    } else if (model->time == 2) {
+        canvas_draw_icon(canvas, 36, 2, &I_ir_ani_3_32x22);
+    }
 }
 
 void xremote_transmit_draw_pause(Canvas* canvas, XRemoteTransmitModel* model) {
@@ -66,12 +70,16 @@ void xremote_transmit_draw_pause(Canvas* canvas, XRemoteTransmitModel* model) {
     canvas_set_font(canvas, FontPrimary);
     canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Waiting");
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Sequence");
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+    canvas_draw_str_aligned(canvas, 74, 15, AlignLeft, AlignTop, "Sequence");
+    canvas_draw_str_aligned(canvas, 74, 25, AlignLeft, AlignTop, model->name);
+
+    if (model->time == 0) {
+        canvas_draw_icon(canvas, 9, 28, &I_pause_ani_1_22x23);
+    } else if (model->time == 1) {
+        canvas_draw_icon(canvas, 9, 28, &I_pause_ani_2_22x23);
+    } else if (model->time == 2) {
+        canvas_draw_icon(canvas, 9, 28, &I_pause_ani_3_22x23);
+    }
 }
 
 void xremote_transmit_draw_subghz(Canvas* canvas, XRemoteTransmitModel* model) {
@@ -82,12 +90,16 @@ void xremote_transmit_draw_subghz(Canvas* canvas, XRemoteTransmitModel* model) {
     canvas_set_font(canvas, FontPrimary);
     canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending");
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "SubGhz");
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+    canvas_draw_str_aligned(canvas, 74, 15, AlignLeft, AlignTop, "SubGhz");
+    canvas_draw_str_aligned(canvas, 74, 25, AlignLeft, AlignTop, model->name);
+
+    if (model->time == 0) {
+        canvas_draw_icon(canvas, 15, 1, &I_sg_ani_1_19x13);
+    } else if (model->time == 1) {
+        canvas_draw_icon(canvas, 15, 1, &I_sg_ani_2_19x13);
+    } else if (model->time == 2) {
+        canvas_draw_icon(canvas, 15, 1, &I_sg_ani_3_19x13);
+    }
 }
 
 void xremote_transmit_draw(Canvas* canvas, XRemoteTransmitModel* model) {
@@ -98,6 +110,10 @@ void xremote_transmit_draw(Canvas* canvas, XRemoteTransmitModel* model) {
     } else if(model->type == XRemoteRemoteItemTypePause) {
         xremote_transmit_draw_pause(canvas, model);
     }
+    if (model->time > 2) {
+        model->time = 0;
+    }
+    elements_button_right(canvas, "exit");
 }
 
 bool xremote_transmit_input(InputEvent* event, void* context) {
@@ -106,6 +122,7 @@ bool xremote_transmit_input(InputEvent* event, void* context) {
     if(event->type == InputTypeRelease) {
         switch(event->key) {
         case InputKeyBack:
+        case InputKeyRight:
             with_view_model(
                 instance->view,
                 XRemoteTransmitModel * model,
@@ -123,6 +140,16 @@ bool xremote_transmit_input(InputEvent* event, void* context) {
     return true;
 }
 
+void xremote_transmit_enter(void* context) {
+    furi_assert(context);
+    XRemoteTransmit* instance = (XRemoteTransmit*)context;
+    with_view_model(
+        instance->view,
+        XRemoteTransmitModel * model,
+        { xremote_transmit_model_init(model); },
+        true);
+}
+
 XRemoteTransmit* xremote_transmit_alloc() {
     XRemoteTransmit* instance = malloc(sizeof(XRemoteTransmit));
     instance->view = view_alloc();
@@ -130,7 +157,7 @@ XRemoteTransmit* xremote_transmit_alloc() {
     view_set_context(instance->view, instance);
     view_set_draw_callback(instance->view, (ViewDrawCallback)xremote_transmit_draw);
     view_set_input_callback(instance->view, xremote_transmit_input);
-    view_set_enter_callback(instance->view, xremote_transmit_enter);
+    //view_set_enter_callback(instance->view, xremote_transmit_enter);
 
     with_view_model(
         instance->view,
@@ -141,16 +168,6 @@ XRemoteTransmit* xremote_transmit_alloc() {
     return instance;
 }
 
-void xremote_transmit_enter(void* context) {
-    furi_assert(context);
-    XRemoteTransmit* instance = (XRemoteTransmit*)context;
-    with_view_model(
-        instance->view,
-        XRemoteTransmitModel * model,
-        { xremote_transmit_model_init(model); },
-        true);
-}
-
 void xremote_transmit_free(XRemoteTransmit* instance) {
     furi_assert(instance);
 

+ 2 - 1
xremote.c

@@ -52,6 +52,7 @@ XRemote* xremote_app_alloc() {
     app->sg_timing_char = "500";
     app->stop_transmit = false;
     app->loop_transmit = 0;
+    app->transmit_item = 0;
 
     // Load configs
     xremote_read_settings(app);
@@ -173,7 +174,7 @@ void xremote_app_free(XRemote* app) {
 
     app->gui = NULL;
     app->notification = NULL;
-
+    
     //Remove whatever is left
     free(app);
 }

+ 1 - 0
xremote.h

@@ -50,6 +50,7 @@ typedef struct {
     char* sg_timing_char;
     bool transmitting;
     bool stop_transmit;
+    size_t transmit_item;
     char text_store[XREMOTE_TEXT_STORE_NUM][XREMOTE_TEXT_STORE_SIZE + 1];
     SubGhz* subghz;
     NumberInput* number_input;

+ 2 - 2
xremote_i.h

@@ -51,10 +51,10 @@
 #define XREMOTE_TEXT_STORE_SIZE 128
 #define XREMOTE_MAX_ITEM_NAME_LENGTH 22
 #define XREMOTE_MAX_REMOTE_NAME_LENGTH 22
-#define XREMOTE_VERSION "2.8"
+#define XREMOTE_VERSION "3.0"
 
 #define INFRARED_APP_EXTENSION ".ir"
-#define INFRARED_APP_FOLDER ANY_PATH("infrared")
+#define INFRARED_APP_FOLDER EXT_PATH("infrared")
 
 #define SUBGHZ_APP_EXTENSION ".sub"