Skip to content

Commit

Permalink
v1.0
Browse files Browse the repository at this point in the history
First released version
  • Loading branch information
wildhart committed Jan 15, 2016
1 parent 219f5e6 commit d75dd59
Show file tree
Hide file tree
Showing 13 changed files with 367 additions and 65 deletions.
17 changes: 14 additions & 3 deletions appinfo.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
{
"appKeys": {},
"appKeys": {
"KEY_ALARM": 2,
"KEY_MEDICATIONS": 100,
"KEY_MODE": 1,
"KEY_SORT": 3
},
"capabilities": [
""
"configurable"
],
"companyName": "[email protected]",
"longName": "Medication Timer",
"projectType": "native",
"resources": {
"media": [
{
"file": "images/menu_icon.png",
"menuIcon": true,
"name": "IMAGE_MENU_ICON",
"type": "png"
},
{
"file": "images/icons.png",
"name": "IMAGE_ICON_MATRIX",
Expand All @@ -16,7 +27,7 @@
]
},
"sdkVersion": "2",
"shortName": "Medication Timer",
"shortName": "Meds Timer",
"uuid": "95d07e1a-2451-4ffa-aa44-836e523a7648",
"versionCode": 1,
"versionLabel": "1.0",
Expand Down
Binary file added resources/images/menu_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 11 additions & 14 deletions src/job_adjust.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@
#define N_LAYERS 1
#define BUFFER_LENGTH 6
static uint8_t active_layer;
static uint16_t limits[N_LAYERS]={24};
static uint16_t limits[N_LAYERS]={25};
static uint16_t values[N_LAYERS];
static const char* formats[N_LAYERS]={"%d"};
static char buffers[N_LAYERS][BUFFER_LENGTH];
static uint8_t job_index;

static Window *s_window;
static GFont s_res_gothic_24_bold;
static GFont s_res_gothic_18;
static GFont s_res_gothic_14;
static ActionBarLayer *s_actionbarlayer;
static TextLayer *s_textlayer_name;
static TextLayer *s_textlayer_hrs;
static TextLayer *layers[N_LAYERS];
static TextLayer *s_textlayer_help;

static void action_bar_up_click_handler() {
values[active_layer]=(values[active_layer]+1) % limits[active_layer];
Expand All @@ -32,7 +31,7 @@ static void action_bar_down_click_handler() {

static void action_bar_select_click_handler() {
if (active_layer==N_LAYERS-1) {
jobs_set_job_repeat(job_index,values[0]);
jobs_set_job_repeat(&job_index,values[0]); // this updates job_index if it gets moved during sort
job_adjust_hide();
return;
}
Expand Down Expand Up @@ -68,25 +67,24 @@ static void initialise_ui(void) {
text_layer_set_font(s_textlayer_name, s_res_gothic_24_bold);
layer_add_child(window_get_root_layer(s_window), (Layer *)s_textlayer_name);

// s_textlayer_hrs
s_textlayer_hrs = text_layer_create(GRect(30+20+4, 60, 30, 24));
text_layer_set_font(s_textlayer_hrs, s_res_gothic_18);
text_layer_set_text(s_textlayer_hrs, "hrs");
layer_add_child(window_get_root_layer(s_window), (Layer *)s_textlayer_hrs);

for (uint8_t l=0; l<N_LAYERS; l++) {
layers[l] = text_layer_create(GRect(30+20*l, 60, 20, 24));
text_layer_set_text_alignment(layers[l], GTextAlignmentCenter);
text_layer_set_font(layers[l], s_res_gothic_18);
layer_add_child(window_get_root_layer(s_window), (Layer *)layers[l]);
}

// s_textlayer_help
s_textlayer_help = text_layer_create(GRect(5, 118, 109, 34));
text_layer_set_text(s_textlayer_help, "SHORT press: 1 unit\nLONG press: 5 units");
text_layer_set_font(s_textlayer_help, s_res_gothic_14);
layer_add_child(window_get_root_layer(s_window), (Layer *)s_textlayer_help);
}

static void destroy_ui(void) {
window_destroy(s_window);
action_bar_layer_destroy(s_actionbarlayer);
text_layer_destroy(s_textlayer_name);
text_layer_destroy(s_textlayer_help);

for (uint8_t l=0; l<N_LAYERS; l++) text_layer_destroy(layers[l]);
}
Expand All @@ -95,13 +93,12 @@ static void handle_window_unload(Window* window) {
destroy_ui();
}

void job_adjust_show(uint8_t index) {
void job_adjust_show() {
initialise_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
job_index=index;
text_layer_set_text(s_textlayer_name, jobs_get_job_name(index));
text_layer_set_text(s_textlayer_name, jobs_get_job_name(job_index));
active_layer=0;
values[0]=jobs_get_job_repeat(job_index);
for (uint8_t l=0; l<N_LAYERS; l++) {
Expand Down
2 changes: 1 addition & 1 deletion src/job_adjust.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once

void job_adjust_show(uint8_t job_index);
void job_adjust_show(void);
void job_adjust_hide(void);
8 changes: 4 additions & 4 deletions src/job_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,18 @@ static void menu_select_callback(MenuLayer *menu_layer, MenuIndex *cell_index, v
switch (cell_index->row) {
case MENU_RESET:
jobs_reset_and_save(job_index);
menu_layer_reload_data(s_menulayer);
job_menu_hide();
break;
case MENU_ADD10:
jobs_add_minutes(job_index, -10);
jobs_add_minutes(&job_index, (settings.Mode==MODE_NEXT_TIME) ? 10:-10); // this updates job_index incase it gets sorted
menu_layer_reload_data(s_menulayer);
break;
case MENU_SUB10:
jobs_add_minutes(job_index, 10);
jobs_add_minutes(&job_index, (settings.Mode==MODE_NEXT_TIME) ? -10:10); // this updates job_index incase it gets sorted
menu_layer_reload_data(s_menulayer);
break;
case MENU_RENAME: jobs_rename_job(job_index); break;
case MENU_ADJUST: job_adjust_show(job_index); break;
case MENU_ADJUST: job_adjust_show(); break;
case MENU_DELETE:
jobs_delete_job_and_save(job_index);
job_menu_hide();
Expand Down
2 changes: 2 additions & 0 deletions src/job_menu.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

extern uint8_t job_index;

void job_menu_show(uint8_t index);
void job_menu_hide(void);
void job_menu_update(void);
156 changes: 142 additions & 14 deletions src/jobs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#define JOB_NAME_LENGTH 24
typedef struct {
char Name[JOB_NAME_LENGTH];
uint32_t Seconds;
time_t Seconds;
uint8_t Repeat_hrs;
} Job;

Expand All @@ -19,15 +19,15 @@ uint8_t jobs_count=0;
// JOB LIST FUNCTIONS
// *****************************************************************************************************

static void jobs_list_append_job(const char* name) {
static void jobs_list_append_job(const char* name, time_t seconds, uint8_t repeat) {
Job* new_job = malloc(sizeof(Job));
Job_ptr* new_job_ptr = malloc(sizeof(Job_ptr));

new_job_ptr->Job = new_job;
new_job_ptr->Next_ptr = NULL;
strncpy(new_job->Name, name, JOB_NAME_LENGTH);
new_job->Seconds = time(NULL);
new_job->Repeat_hrs = 0;
new_job->Seconds = seconds;
new_job->Repeat_hrs = repeat;

if (first_job_ptr) {
Job_ptr* last_job_ptr = first_job_ptr;
Expand All @@ -40,6 +40,34 @@ static void jobs_list_append_job(const char* name) {
main_save_data();
}

void jobs_list_sort(void) {
time_t end_time;

Job_ptr* job_ptr_before = first_job_ptr;
while (job_ptr_before && job_ptr_before->Next_ptr) {
end_time = END_TIME(job_ptr_before->Job);
Job_ptr* job_ptr_min = job_ptr_before;

Job_ptr* job_ptr_loop = job_ptr_before->Next_ptr;
while (job_ptr_loop) {
if (END_TIME(job_ptr_loop->Job) < end_time) {
end_time = END_TIME(job_ptr_loop->Job);
job_ptr_min = job_ptr_loop;
}
job_ptr_loop = job_ptr_loop->Next_ptr;
}

if (job_ptr_min != job_ptr_before) {
// swap med
Job* temp_job = job_ptr_before->Job;
job_ptr_before->Job = job_ptr_min->Job;
job_ptr_min->Job = temp_job;
}

job_ptr_before = job_ptr_before->Next_ptr;
}
}

void jobs_list_save(uint8_t first_key) {
Job_ptr* job_ptr = first_job_ptr;
while (job_ptr) {
Expand All @@ -50,15 +78,49 @@ void jobs_list_save(uint8_t first_key) {
persist_delete(first_key);
}

void jobs_list_write_dict(DictionaryIterator *iter, uint8_t first_key) {
Job_ptr* job_ptr = first_job_ptr;
Job * job;
char buffer[JOB_NAME_LENGTH+30];
while (job_ptr) {
job=job_ptr->Job;
snprintf(buffer,JOB_NAME_LENGTH+30,"%s|%ld|%u",job->Name, job->Seconds, job->Repeat_hrs);
dict_write_cstring(iter, first_key++, buffer);
job_ptr=job_ptr->Next_ptr;
}
}

void jobs_list_read_dict(DictionaryIterator *iter, uint8_t first_key) {
if (first_job_ptr!=NULL) return;

Tuple *tuple_t;
char buffer[3][JOB_NAME_LENGTH];

while ((tuple_t=dict_find(iter, first_key++))) {
char *source = tuple_t->value->cstring;
for (int c=0; c<3; c++) {
uint d=0; // destination offset
while (*source && *source!='|' && d<JOB_NAME_LENGTH) {
buffer[c][d++]=*source++;
}
while (*source && *source!='|') source++;
buffer[c][d]=0;
source++;
}
jobs_list_append_job(buffer[0], atoi(buffer[1]), atoi(buffer[2]));
}
}

void jobs_list_load2(uint8_t first_key, const uint8_t version) {
jobs_list_append_job("Paracetamol");
jobs_list_append_job("Ibuprofin");
jobs_list_append_job("Paracetamol",time(NULL),0);
jobs_list_append_job("Ibuprofin",time(NULL),0);
}

void jobs_list_load(uint8_t first_key, const uint8_t version) {
Job* new_job;
Job_ptr* new_job_ptr;
Job_ptr* prev_job_ptr=NULL;
LOG("key=%d, exists=%d", first_key, persist_exists(first_key));
while (persist_exists(first_key)) {
new_job = malloc(sizeof(Job));
persist_read_data(first_key, new_job, sizeof(Job));
Expand All @@ -72,6 +134,7 @@ void jobs_list_load(uint8_t first_key, const uint8_t version) {
jobs_count++;
first_key++;
}
LOG("Loaded %d jobs.",jobs_count);
}

Job* jobs_list_get_index(uint8_t index) {
Expand Down Expand Up @@ -103,9 +166,8 @@ void jobs_list_move_to_top(uint8_t index) {
static void callback(const char* result, size_t result_length, void* extra) {
// Do something with result
int index = (int) extra;
LOG("%d",index);
if (index==-1) {
jobs_list_append_job(result);
jobs_list_append_job(result, time(NULL), 0);
} else {
snprintf(jobs_list_get_index(index)->Name,JOB_NAME_LENGTH, result);
main_save_data();
Expand Down Expand Up @@ -159,20 +221,49 @@ uint8_t jobs_get_job_repeat(uint8_t index) {
return (job) ? job->Repeat_hrs : 0;
}

void jobs_set_job_repeat(uint8_t index, uint8_t repeat) {
Job* job=jobs_list_get_index(index);
static void jobs_update_job_index(Job* job, uint8_t *index) {
// check if job was moved during sort
if (job==jobs_list_get_index(*index)) return;
// get new index
Job_ptr* job_ptr = first_job_ptr;
*index=0;
while (job_ptr->Job != job) {
(*index)++;
job_ptr=job_ptr->Next_ptr;
}
}

void jobs_set_job_repeat(uint8_t *index, uint8_t repeat) {
Job* job=jobs_list_get_index(*index);
if (job) job->Repeat_hrs=repeat;
main_save_data();
jobs_update_job_index(job, index);
}

#define MAX_CLOCK_LENGTH 24
char clock_buffer[MAX_CLOCK_LENGTH];
char repeat_buffer[MAX_CLOCK_LENGTH];

char* jobs_get_job_clock_as_text(uint8_t index) {
int seconds = jobs_get_job_seconds(index);
Job* job=jobs_list_get_index(index);
time_t seconds;

snprintf(clock_buffer,MAX_CLOCK_LENGTH,"%d:%02d:%02d",(seconds/3600) /*hours*/,(seconds / 60) % 60 /*mins*/,seconds % 60 /*secs*/);
switch (settings.Mode) {
case MODE_COUNT_DOWN:
seconds = job->Seconds + job->Repeat_hrs*3600 - time(NULL);
bool minus = seconds < 0;
if (minus) seconds = -seconds;
snprintf(clock_buffer,MAX_CLOCK_LENGTH,"%s%ld:%02ld:%02ld",minus?"+":"-",(seconds/3600) /*hours*/,(seconds / 60) % 60 /*mins*/,seconds % 60 /*secs*/);
break;
case MODE_COUNT_UP:
seconds = time(NULL) - job->Seconds;
snprintf(clock_buffer,MAX_CLOCK_LENGTH,"%ld:%02ld:%02ld",(seconds/3600) /*hours*/,(seconds / 60) % 60 /*mins*/,seconds % 60 /*secs*/);
break;
case MODE_NEXT_TIME:
; time_t next = END_TIME(job);
strftime(clock_buffer,MAX_CLOCK_LENGTH,clock_is_24h_style() ? "%H:%M" : "%I:%M %p",localtime(&next));
break;
}
return clock_buffer;
}

Expand All @@ -188,8 +279,8 @@ void jobs_reset_and_save(uint8_t index) {
main_save_data();
}

void jobs_add_minutes(uint8_t index, int minutes) {
Job* job=jobs_list_get_index(index);
void jobs_add_minutes(uint8_t *index, int minutes) {
Job* job=jobs_list_get_index(*index);
int seconds = (int) job->Seconds;
if (seconds + 60*minutes < time(NULL)) {
seconds += 60*minutes;
Expand All @@ -198,4 +289,41 @@ void jobs_add_minutes(uint8_t index, int minutes) {
}
job->Seconds = seconds;
main_save_data();
jobs_update_job_index(job, index);
}

time_t jobs_get_next_wakeup_time(void) {
Job_ptr* job_ptr = first_job_ptr;
time_t min_time = (END_TIME(job_ptr->Job) > time(NULL)) ? END_TIME(job_ptr->Job) : 0;

while (job_ptr) {
if (job_ptr->Job->Repeat_hrs && END_TIME(job_ptr->Job) > time(NULL) && (min_time==0 || END_TIME(job_ptr->Job)<min_time)) min_time = END_TIME(job_ptr->Job);
job_ptr = job_ptr->Next_ptr;
}
return min_time;
}

static void vibrate(void) {
// Vibe pattern: ON for 200ms, OFF for 100ms, ON for 400ms:
LOG("VIBRATE!!!");
static const uint32_t segments[] = { 400,200, 400,200, 400,200, 400,200, 400 };
VibePattern pat = {
.durations = segments,
.num_segments = ARRAY_LENGTH(segments),
};
vibes_enqueue_custom_pattern(pat);
}

static uint8_t jobs_alarm_count = 0;

void jobs_check_alarms(void) {
if (!jobs_count || !settings.Alarm) return;
uint8_t new_alarm_count=0;
Job_ptr* job_ptr = first_job_ptr;
while (job_ptr) {
if (job_ptr->Job->Repeat_hrs && END_TIME(job_ptr->Job) <= time(NULL)) new_alarm_count++;
job_ptr=job_ptr->Next_ptr;
}
if (new_alarm_count>jobs_alarm_count) vibrate();
jobs_alarm_count=new_alarm_count;
}
Loading

0 comments on commit d75dd59

Please sign in to comment.