Skip to content
This repository has been archived by the owner on Apr 27, 2020. It is now read-only.

Commit

Permalink
Added Pebble Health integration
Browse files Browse the repository at this point in the history
The top half of the text now displays the number of steps taken today.
  • Loading branch information
aaronhktan committed Nov 12, 2016
1 parent 8579b97 commit e7698b9
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 62 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"name": "breathe",
"pebble": {
"capabilities": [
"configurable"
"configurable",
"health"
],
"displayName": "Breathe",
"enableMultiJS": true,
Expand Down
136 changes: 75 additions & 61 deletions src/c/breathe_window.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <pebble.h>
#include "breathe_window.h"
#include "src/c/data.h"

//creates a pointer for main window
static Window *s_main_window;
Expand All @@ -11,8 +12,9 @@ static uint8_t s_radius_final, s_radius = 0;
static int s_min_to_breathe = 1, s_times_clicked_select = 0, s_times_played = 0;
static bool s_animation_completed = false, s_animating = false;
static GPoint s_center;
static char s_min_to_breathe_text[3] = "1", s_instruct_text[8], s_min_text[5], s_min_today[19] = "BREATHED TODAY: 0", s_greet_text[19] = "HELLO, AARON";
static char s_min_to_breathe_text[3] = "1", s_instruct_text[8], s_min_text[5], s_min_today[19] = "TODAY: 0 MIN", s_greet_text[19] = "HELLO.";
static time_t t;
ClaySettings settings;

// Depending on display size, change location of up and down arrows
#if PBL_DISPLAY_HEIGHT == 168
Expand Down Expand Up @@ -44,9 +46,8 @@ static time_t t;
};
#endif

ClaySettings settings;

// ******************************************************************************************* Settings Procedures
// Loads default settings; if user has set settings, then other settings are loaded
static void load_settings() {
settings.backgroundColor = GColorBlack;
settings.circleColor = PBL_IF_COLOR_ELSE(GColorJaegerGreen, GColorWhite);
Expand All @@ -66,68 +67,79 @@ static void canvas_update_proc(Layer *s_drawing_layer, GContext *ctx) {
// updates text inside circle, side semicircle, and triangles
static void inside_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {

//draw side circle
graphics_context_set_fill_color(ctx, settings.textColor);
graphics_fill_circle(ctx, GPoint(bounds.size.w + 5, bounds.size.h / 2), 10);

// draw triangles
switch(s_min_to_breathe) {
case 1 :
gpath_draw_filled(ctx, s_up_triangle);
break;
case 10 :
gpath_draw_filled(ctx, s_down_triangle);
break;
default:
gpath_draw_filled(ctx, s_up_triangle);
gpath_draw_filled(ctx, s_down_triangle);
}

// draw text in circle
graphics_context_set_text_color(ctx, settings.textColor);
GSize min_to_breathe_bounds = graphics_text_layout_get_content_size("10", fonts_get_system_font(FONT_KEY_LECO_42_NUMBERS),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_min_to_breathe_text, fonts_get_system_font(FONT_KEY_LECO_42_NUMBERS),
GRect((bounds.size.w - min_to_breathe_bounds.w) / 2, (bounds.size.h - min_to_breathe_bounds.h) / 2 - 6, min_to_breathe_bounds.w, min_to_breathe_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);

GSize instruct_text_bounds = graphics_text_layout_get_content_size("BREATHE", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_instruct_text, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - instruct_text_bounds.w) / 2, (bounds.size.h - instruct_text_bounds.h) / 2 - 29, instruct_text_bounds.w, instruct_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
//draw side circle
graphics_context_set_fill_color(ctx, settings.textColor);
graphics_fill_circle(ctx, GPoint(bounds.size.w + 5, bounds.size.h / 2), 10);

// draw triangles
switch(s_min_to_breathe) {
case 1 :
gpath_draw_filled(ctx, s_up_triangle);
break;
case 10 :
gpath_draw_filled(ctx, s_down_triangle);
break;
default:
gpath_draw_filled(ctx, s_up_triangle);
gpath_draw_filled(ctx, s_down_triangle);
}

GSize min_text_bounds = graphics_text_layout_get_content_size("MINS", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_min_text, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - min_text_bounds.w) / 2, (bounds.size.h - min_text_bounds.h) / 2 + 25, min_text_bounds.w, min_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
// draw text in circle
graphics_context_set_text_color(ctx, settings.textColor);
GSize min_to_breathe_bounds = graphics_text_layout_get_content_size("10", fonts_get_system_font(FONT_KEY_LECO_42_NUMBERS),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_min_to_breathe_text, fonts_get_system_font(FONT_KEY_LECO_42_NUMBERS),
GRect((bounds.size.w - min_to_breathe_bounds.w) / 2, (bounds.size.h - min_to_breathe_bounds.h) / 2 - 6, min_to_breathe_bounds.w, min_to_breathe_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);

GSize instruct_text_bounds = graphics_text_layout_get_content_size("BREATHE", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_instruct_text, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - instruct_text_bounds.w) / 2, (bounds.size.h - instruct_text_bounds.h) / 2 - 29, instruct_text_bounds.w, instruct_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);

GSize min_text_bounds = graphics_text_layout_get_content_size("MINS", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_min_text, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - min_text_bounds.w) / 2, (bounds.size.h - min_text_bounds.h) / 2 + 25, min_text_bounds.w, min_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
}

// draws text at top of screen
static void upper_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
graphics_context_set_text_color(ctx, (s_animating) ? settings.textColor : PBL_IF_COLOR_ELSE(GColorDarkGray, settings.textColor));
GSize greet_text_bounds = graphics_text_layout_get_content_size("HELLO, SAMANTHA", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
#if defined(PBL_HEALTH)
int current_steps = data_get_current_steps();
const char *steps_buffer = data_get_current_steps_buffer();
#endif

graphics_context_set_text_color(ctx, (s_animating) ? settings.textColor : PBL_IF_COLOR_ELSE(GColorDarkGray, settings.textColor));
GSize greet_text_bounds = graphics_text_layout_get_content_size("10,000 STEPS TODAY OMG", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
if (s_animating) {
graphics_draw_text(ctx, s_greet_text, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - greet_text_bounds.w) / 2, 5, greet_text_bounds.w, greet_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
} else {
graphics_draw_text(ctx, PBL_IF_HEALTH_ELSE(steps_buffer, s_greet_text), fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - greet_text_bounds.w) / 2, 5, greet_text_bounds.w, greet_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
}
}

// draws text at bottom of screen
static void lower_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
graphics_context_set_text_color(ctx, (s_animating) ? settings.textColor : PBL_IF_COLOR_ELSE(GColorDarkGray, settings.textColor));
GSize today_text_bounds = graphics_text_layout_get_content_size("BREATHED TODAY: 10", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);
graphics_draw_text(ctx, s_min_today, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - today_text_bounds.w) / 2, bounds.size.h - today_text_bounds.h - 8, today_text_bounds.w, today_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
graphics_context_set_text_color(ctx, (s_animating) ? settings.textColor : PBL_IF_COLOR_ELSE(GColorDarkGray, settings.textColor));
GSize today_text_bounds = graphics_text_layout_get_content_size("TODAY: 10 MINUTES", fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect(0, 0, bounds.size.w, bounds.size.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter);

graphics_draw_text(ctx, s_min_today, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
GRect((bounds.size.w - today_text_bounds.w) / 2, bounds.size.h - today_text_bounds.h - 8, today_text_bounds.w, today_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
}

// ******************************************************************************************* Animation Stuff
Expand Down Expand Up @@ -304,8 +316,12 @@ static void animation_start_callback(void *context) {
// end animation show text
static void animation_end_callback(void *context) {
s_animation_completed = true;
snprintf(s_greet_text, 19, "%s", "HELLO, AARON");
snprintf(s_min_today, 19, "BREATHED TODAY: %d", s_times_clicked_select);
snprintf(s_greet_text, 19, "%s", "HELLO.");
if (s_times_clicked_select > 9) {
snprintf(s_min_today, 19, "TODAY: %dd MIN", s_times_clicked_select);
} else {
snprintf(s_min_today, 19, "TODAY: %d MIN", s_times_clicked_select);
}
if (s_min_to_breathe == 10) {
snprintf(s_min_to_breathe_text, 3, "%dd", s_min_to_breathe);
} else {
Expand Down Expand Up @@ -357,11 +373,6 @@ static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
layer_set_hidden(s_inside_text_layer, true);
layer_set_hidden(s_upper_text_layer, true);
layer_set_hidden(s_lower_text_layer, true);
if (s_times_clicked_select > 9) {
snprintf(s_min_today, 19, "BREATHED TODAY: %dd", s_times_clicked_select);
} else {
snprintf(s_min_today, 19, "BREATHED TODAY: %d", s_times_clicked_select);
}

main_animation_start();

Expand All @@ -388,13 +399,16 @@ static void click_config_provider(void *context) {
}

// ******************************************************************************************* Main App Functions

// Save settings and reload visual aspects
static void save_settings() {
persist_write_data(SETTINGS_KEY, &settings, sizeof(settings));
window_set_background_color(s_main_window, settings.backgroundColor);
layer_mark_dirty(s_circle_layer);
layer_mark_dirty(s_inside_text_layer);
}

// Receive settings from phone
static void inbox_received_handler(DictionaryIterator *iter, void *context) {
Tuple *bg_color_t = dict_find(iter, MESSAGE_KEY_backgroundColor);
if (bg_color_t) {
Expand Down
36 changes: 36 additions & 0 deletions src/c/data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <pebble.h>
#include "data.h"

static int s_current_steps;
static char s_current_steps_buffer[19];

void data_update_steps_buffer() {
int thousands = s_current_steps / 1000;
int hundreds = s_current_steps % 1000;
if(thousands > 0) {
snprintf(s_current_steps_buffer, sizeof(s_current_steps_buffer), "%d,%03d STEPS TODAY", thousands, hundreds);
} else {
snprintf(s_current_steps_buffer, sizeof(s_current_steps_buffer), "%d STEPS TODAY", hundreds);
}
}

static void load_health_data_handler() {
s_current_steps = health_service_sum_today(HealthMetricStepCount);
data_update_steps_buffer();
}

void data_init() {
app_timer_register(500, load_health_data_handler, NULL);
}

int data_get_current_steps() {
return s_current_steps;
}

void data_set_current_steps(int value) {
s_current_steps = value;
}

char* data_get_current_steps_buffer() {
return s_current_steps_buffer;
}
11 changes: 11 additions & 0 deletions src/c/data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "src/c/breathe_window.h"

void data_init();

void data_set_current_steps(int value);
int data_get_current_steps();

void data_update_steps_buffer();

char* data_get_current_steps_buffer();
19 changes: 19 additions & 0 deletions src/c/health.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <pebble.h>
#include "health.h"

static void health_handler(HealthEventType event, void *context) {
data_set_current_steps((int)health_service_sum_today(HealthMetricStepCount));
data_update_steps_buffer();
}

void health_init() {
health_service_events_subscribe(health_handler, NULL);
}

bool health_is_available() {
#if defined(PBL_HEALTH)
return true;
#else
return false;
#endif
}
7 changes: 7 additions & 0 deletions src/c/health.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#include "src/c/data.h"

void health_init();

bool health_is_available();

5 changes: 5 additions & 0 deletions src/c/main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include <pebble.h>
#include "src/c/breathe_window.h"
#include "src/c/data.h"
#include "src/c/health.h"

static void init() {
// Subscribe to health service
health_init();
data_init();
// Show main window
breathe_window_push();
}
Expand Down

0 comments on commit e7698b9

Please sign in to comment.