scene_timer_running.c (4698B)
1 #include "../helpers/ir_helper.h" 2 #include "../helpers/time_helper.h" 3 #include "../timed_remote.h" 4 #include "timed_remote_scene.h" 5 6 static void timer_callback(void *context) { 7 TimedRemoteApp *app = context; 8 view_dispatcher_send_custom_event(app->view_dispatcher, 9 TimedRemoteEventTimerTick); 10 } 11 12 static void update_display(TimedRemoteApp *app) { 13 uint8_t h, m, s; 14 time_helper_seconds_to_hms(app->seconds_remaining, &h, &m, &s); 15 16 char time_str[16]; 17 snprintf(time_str, sizeof(time_str), "%02d:%02d:%02d", h, m, s); 18 19 widget_reset(app->widget); 20 widget_add_string_element(app->widget, 64, 5, AlignCenter, AlignTop, 21 FontSecondary, app->signal_name); 22 widget_add_string_element(app->widget, 64, 25, AlignCenter, AlignTop, 23 FontBigNumbers, time_str); 24 25 if (app->repeat_count > 0 && app->repeat_count < 255) { 26 /* Fixed repeat count (1-99) */ 27 char repeat_str[24]; 28 snprintf(repeat_str, sizeof(repeat_str), "Repeat: %d/%d", 29 app->repeat_count - app->repeats_remaining + 1, app->repeat_count); 30 widget_add_string_element(app->widget, 64, 52, AlignCenter, AlignTop, 31 FontSecondary, repeat_str); 32 } else if (app->repeat_count == 255) { 33 /* Unlimited repeat */ 34 widget_add_string_element(app->widget, 64, 52, AlignCenter, AlignTop, 35 FontSecondary, "Repeat: Unlimited"); 36 } 37 } 38 39 void timed_remote_scene_timer_running_on_enter(void *context) { 40 TimedRemoteApp *app = context; 41 42 /* Calculate initial remaining time */ 43 if (app->timer_mode == TimerModeCountdown) { 44 app->seconds_remaining = 45 time_helper_hms_to_seconds(app->hours, app->minutes, app->seconds); 46 } else { 47 /* Scheduled mode - calculate time until target */ 48 app->seconds_remaining = 49 time_helper_seconds_until(app->hours, app->minutes, app->seconds); 50 if (app->seconds_remaining == 0) { 51 /* Target time already passed - fire immediately */ 52 view_dispatcher_send_custom_event(app->view_dispatcher, 53 TimedRemoteEventTimerFired); 54 return; 55 } 56 } 57 58 /* Initialize repeat tracking for non-repeat or scheduled */ 59 if (app->repeat_count == 0) { 60 app->repeats_remaining = 1; 61 } 62 63 update_display(app); 64 view_dispatcher_switch_to_view(app->view_dispatcher, TimedRemoteViewWidget); 65 66 /* Start 1-second timer */ 67 app->timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, app); 68 furi_timer_start(app->timer, furi_kernel_get_tick_frequency()); /* 1 second */ 69 } 70 71 bool timed_remote_scene_timer_running_on_event(void *context, 72 SceneManagerEvent event) { 73 TimedRemoteApp *app = context; 74 bool consumed = false; 75 76 if (event.type == SceneManagerEventTypeCustom) { 77 if (event.event == TimedRemoteEventTimerTick) { 78 if (app->seconds_remaining > 0) { 79 app->seconds_remaining--; 80 update_display(app); 81 } 82 83 if (app->seconds_remaining == 0) { 84 /* Timer fired! */ 85 view_dispatcher_send_custom_event(app->view_dispatcher, 86 TimedRemoteEventTimerFired); 87 } 88 consumed = true; 89 } else if (event.event == TimedRemoteEventTimerFired) { 90 /* Transmit IR signal */ 91 if (app->ir_signal) { 92 ir_helper_transmit(app->ir_signal); 93 } 94 95 if (app->repeat_count == 255) { 96 /* Unlimited repeat */ 97 app->seconds_remaining = 98 time_helper_hms_to_seconds(app->hours, app->minutes, app->seconds); 99 update_display(app); 100 } else { 101 app->repeats_remaining--; 102 103 if (app->repeat_count != 0 && app->repeats_remaining > 0) { 104 /* Reset countdown for next repeat */ 105 app->seconds_remaining = time_helper_hms_to_seconds( 106 app->hours, app->minutes, app->seconds); 107 update_display(app); 108 } else { 109 /* Done - show confirmation */ 110 scene_manager_next_scene(app->scene_manager, TimedRemoteSceneConfirm); 111 } 112 } 113 consumed = true; 114 } 115 } else if (event.type == SceneManagerEventTypeBack) { 116 /* User pressed Back - cancel timer */ 117 scene_manager_search_and_switch_to_previous_scene(app->scene_manager, 118 TimedRemoteSceneIrBrowse); 119 consumed = true; 120 } 121 122 return consumed; 123 } 124 125 void timed_remote_scene_timer_running_on_exit(void *context) { 126 TimedRemoteApp *app = context; 127 128 /* Stop and free timer */ 129 if (app->timer) { 130 furi_timer_stop(app->timer); 131 furi_timer_free(app->timer); 132 app->timer = NULL; 133 } 134 135 widget_reset(app->widget); 136 }