diff --git a/src/c/main.c b/src/c/main.c index 03d6164..6c73f06 100644 --- a/src/c/main.c +++ b/src/c/main.c @@ -2,12 +2,12 @@ #include // types -typedef struct SetterTime { +typedef struct TheTime { uint8_t HourWIP; uint8_t MinuteWIP; uint8_t HourSet; uint8_t MinuteSet; -} __attribute__((__packed__)) SetterTime; +} __attribute__((__packed__)) TheTime; // layer-age static Window *s_window; @@ -30,7 +30,7 @@ static GBitmap *s_check_bmp; // global vars //// setter static uint8_t s_highlight_pos = 0; -static struct SetterTime s_setter_time; +static struct TheTime s_the_time; // constants //// setter @@ -42,24 +42,49 @@ static const GColor s_highlight_color = GColorMediumAquamarine; ///////////////////////////////// -static void glance_reload_callback(AppGlanceReloadSession *session, size_t limit, void *context) { +static void glance_reload_callback(AppGlanceReloadSession *session, size_t limit, void *target) { static char s_glance_buffer[11]; - snprintf(s_glance_buffer, sizeof(s_glance_buffer), "Up @ %02d:%02d", s_setter_time.HourSet, s_setter_time.MinuteSet); + snprintf(s_glance_buffer, sizeof(s_glance_buffer), "Up @ %02d:%02d", s_the_time.HourSet, s_the_time.MinuteSet); AppGlanceSlice slice = { - .expiration_time = time(NULL) + (7 * SECONDS_PER_DAY), + .expiration_time = (time_t)(uintptr_t)target, .layout.icon = APP_GLANCE_SLICE_DEFAULT_ICON, .layout.subtitle_template_string = s_glance_buffer, }; app_glance_add_slice(session, slice); } +// returns (passes through) the negative value from wakeup_schedule +// when an error is encountered +static int8_t schedule_main_alarm() { + time_t now = time(NULL); + struct tm now_tm = *localtime(&now); + struct tm target_tm = now_tm; + target_tm.tm_hour = s_the_time.HourWIP; + target_tm.tm_min = s_the_time.MinuteWIP; + target_tm.tm_sec = 0; + time_t target = mktime(&target_tm); + if (target <= now) { + target += SECONDS_PER_DAY; + } + wakeup_cancel_all(); + WakeupId status = wakeup_schedule(target, 0, true); + if (status < 0) { + APP_LOG(APP_LOG_LEVEL_DEBUG, "SCHEDULING ERROR: %d", status); + return status; + } + s_the_time.HourSet = s_the_time.HourWIP; + s_the_time.MinuteSet = s_the_time.MinuteWIP; + app_glance_reload(glance_reload_callback, (void *)(uintptr_t)target); + return 0; +} + static void setter_seconds_handler(struct tm *tick_time, TimeUnits units_changed) { struct tm now_tm = *tick_time; // build the target time today struct tm target_tm = now_tm; - target_tm.tm_hour = s_setter_time.HourSet; - target_tm.tm_min = s_setter_time.MinuteSet; + target_tm.tm_hour = s_the_time.HourSet; + target_tm.tm_min = s_the_time.MinuteSet; target_tm.tm_sec = 0; time_t now = mktime(&now_tm); @@ -88,24 +113,24 @@ static void update_countdown_display() { static void update_setter_display() { static char s_setter_buffer[PBL_IF_ROUND_ELSE(8, 12)]; - snprintf(s_setter_buffer, sizeof(s_setter_buffer), PBL_IF_ROUND_ELSE("%02d : %02d", "%02d : %02d"), s_setter_time.HourWIP, s_setter_time.MinuteWIP); + snprintf(s_setter_buffer, sizeof(s_setter_buffer), PBL_IF_ROUND_ELSE("%02d : %02d", "%02d : %02d"), s_the_time.HourWIP, s_the_time.MinuteWIP); text_layer_set_text(s_setter_txt_layer, s_setter_buffer); } static void setter_up_click_handler(void *recognizer, void *ctx) { switch (s_highlight_pos) { case 0: - if (s_setter_time.HourWIP == 23) { - s_setter_time.HourWIP = 0; + if (s_the_time.HourWIP == 23) { + s_the_time.HourWIP = 0; } else { - s_setter_time.HourWIP++; + s_the_time.HourWIP++; } break; case 1: - if (s_setter_time.MinuteWIP == 59) { - s_setter_time.MinuteWIP = 0; + if (s_the_time.MinuteWIP == 59) { + s_the_time.MinuteWIP = 0; } else { - s_setter_time.MinuteWIP++; + s_the_time.MinuteWIP++; } break; default: @@ -117,17 +142,17 @@ static void setter_up_click_handler(void *recognizer, void *ctx) { static void setter_down_click_handler(void *recognizer, void *ctx) { switch (s_highlight_pos) { case 0: - if (s_setter_time.HourWIP == 0) { - s_setter_time.HourWIP = 23; + if (s_the_time.HourWIP == 0) { + s_the_time.HourWIP = 23; } else { - s_setter_time.HourWIP--; + s_the_time.HourWIP--; } break; case 1: - if (s_setter_time.MinuteWIP == 0) { - s_setter_time.MinuteWIP = 59; + if (s_the_time.MinuteWIP == 0) { + s_the_time.MinuteWIP = 59; } else { - s_setter_time.MinuteWIP--; + s_the_time.MinuteWIP--; } break; default: @@ -138,42 +163,20 @@ static void setter_down_click_handler(void *recognizer, void *ctx) { static void setter_select_click_handler(void *recognizer, void *ctx) { if (s_highlight_pos == 2) { - // schedule wakeup - time_t now = time(NULL); - struct tm now_tm = *localtime(&now); - struct tm target_tm = now_tm; - target_tm.tm_hour = s_setter_time.HourWIP; - target_tm.tm_min = s_setter_time.MinuteWIP; - target_tm.tm_sec = 0; - time_t target = mktime(&target_tm); - if (target <= now) { - target += SECONDS_PER_DAY; - } - wakeup_cancel_all(); - WakeupId status; - for (int i = 0; i < 8; ++i) { - status = wakeup_schedule(target, 0, true); - if (status < 0) { - APP_LOG(APP_LOG_LEVEL_DEBUG, "SCHEDULING ERROR: %d", status); - return; - } - target += SECONDS_PER_DAY; + int8_t status = schedule_main_alarm(); + if (status < 0) { + return; // early return to avoid indicating alarm was set when it was not } // persist - s_setter_time.HourSet = s_setter_time.HourWIP; - s_setter_time.MinuteSet = s_setter_time.MinuteWIP; - persist_write_int(STORAGE_KEY_ALARM_HOUR, s_setter_time.HourSet); - persist_write_int(STORAGE_KEY_ALARM_MINUTE, s_setter_time.MinuteSet); + persist_write_int(STORAGE_KEY_ALARM_HOUR, s_the_time.HourSet); + persist_write_int(STORAGE_KEY_ALARM_MINUTE, s_the_time.MinuteSet); // update countdown immediately update_countdown_display(); // move selection back to start s_highlight_pos = 0; - - // set app glance - app_glance_reload(glance_reload_callback, NULL); } else { s_highlight_pos++; } @@ -183,7 +186,7 @@ static void setter_select_click_handler(void *recognizer, void *ctx) { static void setter_back_click_handler(void *recognizer, void *ctx) { if (s_highlight_pos == 0) { - window_stack_pop_all(true); // exit app + window_stack_pop_all(true); } else { s_highlight_pos--; } @@ -224,11 +227,6 @@ static void highlight_layer_update_proc(Layer *layer, GContext *ctx) { } static void setter_window_load() { - s_setter_time.HourSet = persist_read_int(STORAGE_KEY_ALARM_HOUR); - s_setter_time.MinuteSet = persist_read_int(STORAGE_KEY_ALARM_MINUTE); - s_setter_time.HourWIP = s_setter_time.HourSet; - s_setter_time.MinuteWIP = s_setter_time.MinuteSet; - Layer *window_layer = window_get_root_layer(s_window); // top&bottom bars @@ -293,7 +291,23 @@ static void setter_window_unload() { layer_destroy(s_top_bar_layer); } +static void schedule_fallback_alarm() { + wakeup_cancel_all(); + time_t target_time = time(NULL); + WakeupId status; + while (true) { + target_time += 15; + status = wakeup_schedule(target_time, 0, true); + if (status >= 0) { + break; + } + } +} + static void alarm_seconds_handler(struct tm *tick_time, TimeUnits units_changed) { + if (tick_time->tm_sec % 15 == 0) { + schedule_fallback_alarm(); + } vibes_short_pulse(); } @@ -307,6 +321,7 @@ static void alarm_window_load() { text_layer_set_text(s_alarm_txt_layer, "IMAGINE THIS IS A TRIANGLE"); layer_add_child(window_layer, text_layer_get_layer(s_alarm_txt_layer)); + schedule_fallback_alarm(); tick_timer_service_subscribe(SECOND_UNIT, alarm_seconds_handler); } @@ -314,12 +329,35 @@ static void alarm_window_unload() { text_layer_destroy(s_alarm_txt_layer); } +// DEBUG: logic will eventually be mapped to when triangle is solved +static void alarm_select_click_handler(void *recognizer, void *ctx) { + wakeup_cancel_all(); + int8_t status = schedule_main_alarm(); + while (status < 0) { + s_the_time.MinuteWIP++; + if (s_the_time.MinuteWIP >= 60) { + s_the_time.MinuteWIP = 0; + s_the_time.HourWIP++; + if (s_the_time.HourWIP >= 24) { + s_the_time.HourWIP = 0; + } + } + status = schedule_main_alarm(); + } + window_stack_pop_all(true); +} + static void alarm_click_config_provider(void *ctx) { window_single_click_subscribe(BUTTON_ID_BACK, NULL); + window_long_click_subscribe(BUTTON_ID_SELECT, 5000, alarm_select_click_handler, NULL); } static void init() { s_window = window_create(); + s_the_time.HourWIP = persist_read_int(STORAGE_KEY_ALARM_HOUR); + s_the_time.MinuteWIP = persist_read_int(STORAGE_KEY_ALARM_MINUTE); + s_the_time.HourSet = s_the_time.HourWIP; + s_the_time.MinuteSet = s_the_time.MinuteWIP; switch (launch_reason()) { case APP_LAUNCH_WAKEUP: