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

Commit

Permalink
Added Heart Rate feature
Browse files Browse the repository at this point in the history
Not actually sure if it works, but it should. ¯\_(ツ)_/¯ The emulator on CloudPebble doesn't seem to have heart rate emulation, so I can't test it.
  • Loading branch information
aaronhktan committed Nov 14, 2016
1 parent 0e4caa7 commit de2df8a
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 24 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"messageKeys": [
"backgroundColor",
"circleColor",
"vibrationEnabled"
"vibrationEnabled",
"heartRateEnabled"
],
"projectType": "native",
"resources": {
Expand Down
14 changes: 13 additions & 1 deletion src/c/breathe_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ static void load_settings() {
settings.circleColor = PBL_IF_COLOR_ELSE(GColorJaegerGreen, GColorWhite);
settings.textColor = GColorWhite;
settings.vibrationEnabled = true;
#if PBL_API_EXISTS(health_service_peek_current_value)
settings.heartRateEnabled = true;
#else
settings.heartRateEnabled = false;
#endif
persist_read_data(SETTINGS_KEY, &settings, sizeof(settings));
}

Expand All @@ -39,7 +44,7 @@ static void inside_text_layer_update_proc(Layer *s_inside_text_layer, GContext *

// draws text at top of screen
static void upper_text_layer_update_proc(Layer *s_inside_text_layer, GContext *ctx) {
graphics_draw_upper_text(ctx, bounds, s_animating, settings.textColor, s_greet_text);
graphics_draw_upper_text(ctx, bounds, s_animating, settings.heartRateEnabled, settings.textColor, s_greet_text);
}

// draws text at bottom of screen
Expand Down Expand Up @@ -317,6 +322,7 @@ static void save_settings() {
window_set_background_color(s_main_window, settings.backgroundColor);
layer_mark_dirty(s_circle_layer);
layer_mark_dirty(s_inside_text_layer);
layer_mark_dirty(s_upper_text_layer);
}

// Receive settings from phone
Expand All @@ -331,6 +337,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "The background color is white.");
settings.textColor = GColorBlack;
}
settings.circleColor = settings.textColor;
}

Tuple *circle_color_t = dict_find(iter, MESSAGE_KEY_circleColor);
Expand All @@ -343,6 +350,11 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
settings.vibrationEnabled = vibration_enabled_t->value->int32 == 1;
}

Tuple *heartRate_enabled_t = dict_find(iter, MESSAGE_KEY_heartRateEnabled);
if (heartRate_enabled_t) {
settings.heartRateEnabled = heartRate_enabled_t->value->int32 == 1;
}

save_settings();
}

Expand Down
1 change: 1 addition & 0 deletions src/c/breathe_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ typedef struct ClaySettings {
GColor circleColor;
GColor textColor;
bool vibrationEnabled;
bool heartRateEnabled;
} ClaySettings;

void breathe_window_push();
25 changes: 23 additions & 2 deletions src/c/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#include "data.h"

static int s_current_steps;
static char s_current_steps_buffer[19];
HealthValue s_current_heart_rate;
static char s_current_steps_buffer[19], s_current_heart_rate_buffer[8];

void data_update_steps_buffer() {
int thousands = s_current_steps / 1000;
Expand All @@ -14,9 +15,17 @@ void data_update_steps_buffer() {
}
}

void data_update_heart_rate_buffer() {
snprintf(s_current_heart_rate_buffer, sizeof(s_current_heart_rate_buffer), "%lu BPM", (uint32_t) s_current_heart_rate);
}

static void load_health_data_handler() {
s_current_steps = health_service_sum_today(HealthMetricStepCount);
data_update_steps_buffer();
#if PBL_API_EXISTS(health_service_peek_current_value)
s_current_heart_rate = health_service_peek_current_value(HealthMetricHeartRateBPM);
data_update_heart_rate_buffer();
#endif
}

void data_init() {
Expand All @@ -31,10 +40,22 @@ void data_set_current_steps(int value) {
s_current_steps = value;
}

int data_get_current_heart_rate() {
return s_current_heart_rate;
}

void data_set_current_heart_rate(int value) {
s_current_heart_rate = value;
}

char* data_get_current_steps_buffer() {
return s_current_steps_buffer;
}

char* data_get_current_heart_rate_buffer() {
return s_current_heart_rate_buffer;
}

char *data_get_date_today() {
time_t temp = time(NULL);
struct tm *tick_time = localtime(&temp);
Expand All @@ -45,7 +66,7 @@ char *data_get_date_today() {

void data_write_breathe_persist_data(int min_breathed_today){
persist_write_int(MIN_BREATHED_TODAY_KEY, min_breathed_today);
APP_LOG(APP_LOG_LEVEL_DEBUG, "The minutes breathed today are: %dd", min_breathed_today);
APP_LOG(APP_LOG_LEVEL_DEBUG, "The minutes breathed today are: %d", min_breathed_today);
}

void data_write_date_persist_data() {
Expand Down
7 changes: 6 additions & 1 deletion src/c/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@

void data_init();

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

int data_get_current_heart_rate();
void data_set_current_heart_rate(int value);

void data_update_steps_buffer();
void data_update_heart_rate_buffer();

char* data_get_current_steps_buffer();
char* data_get_current_heart_rate_buffer();

char* data_get_date_today();
void data_write_breathe_persist_data(int min_to_breathe);
Expand Down
11 changes: 9 additions & 2 deletions src/c/graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static GPath *s_up_triangle, *s_down_triangle;
};
#endif

void graphics_draw_upper_text(GContext *ctx, GRect bounds, bool is_animating, GColor textColor, char *greet_text) {
void graphics_draw_upper_text(GContext *ctx, GRect bounds, bool is_animating, bool heart_rate, GColor textColor, char *greet_text) {
#if defined(PBL_HEALTH)
const char *steps_buffer = data_get_current_steps_buffer();
#endif
Expand All @@ -47,9 +47,16 @@ void graphics_draw_upper_text(GContext *ctx, GRect bounds, bool is_animating, GC
GRect((bounds.size.w - greet_text_bounds.w) / 2, 5, greet_text_bounds.w, greet_text_bounds.h),
GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
} else {
graphics_draw_text(ctx, PBL_IF_HEALTH_ELSE(steps_buffer, greet_text), fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD),
if (heart_rate && data_get_current_heart_rate() > 0) {
const char *heart_rate_buffer = data_get_current_heart_rate_buffer();
graphics_draw_text(ctx, heart_rate_buffer, 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);
} else {
graphics_draw_text(ctx, PBL_IF_HEALTH_ELSE(steps_buffer, 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);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/c/graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <pebble.h>
#include "src/c/data.h"

void graphics_draw_upper_text(GContext *ctx, GRect bounds, bool is_animating, GColor textColor, char *);
void graphics_draw_upper_text(GContext *ctx, GRect bounds, bool is_animating, bool heart_rate, GColor textColor, char *);

void graphics_draw_lower_text(GContext *ctx, GRect bounds, bool is_animating, GColor textColor, char *);

Expand Down
18 changes: 9 additions & 9 deletions src/c/health.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
#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();
if (event == HealthEventHeartRateUpdate) {
data_set_current_heart_rate((int)health_service_peek_current_value(HealthMetricHeartRateBPM));
data_update_heart_rate_buffer();
} else if (event == HealthEventMovementUpdate) {
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;
#if PBL_API_EXISTS(health_service_set_heart_rate_sample_period)
health_service_set_heart_rate_sample_period(0);
#endif
}
5 changes: 1 addition & 4 deletions src/c/health.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#pragma once
#include "src/c/data.h"

void health_init();

bool health_is_available();

void health_init();
7 changes: 6 additions & 1 deletion src/c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
static void init() {
APP_LOG(APP_LOG_LEVEL_DEBUG, "You are running the most recent version of this app.");
// Subscribe to health service
health_init();
#if PBL_HEALTH
health_init();
#endif
data_init();
// Show main window
breathe_window_push();
}

static void deinit() {
#if PBL_API_EXISTS(health_service_set_heart_rate_sample_period)
health_service_set_heart_rate_sample_period(0);
#endif
}

int main(void) {
Expand Down
21 changes: 21 additions & 0 deletions src/pkjs/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ module.exports = [
"type": "heading",
"defaultValue": "Configuration Page"
},
{
"type": "text",
"defaultValue": "This is the settings page. Feel free to change anything you want. You are running version 0.1.2 of Breathe.",
},
{
"type": "section",
"items": [
Expand All @@ -23,6 +27,7 @@ module.exports = [
"defaultValue": "00AA55",
"label": "Circle Color",
"sunlight": true,
"capabilities": ["COLOR"]
}
]
},
Expand All @@ -40,6 +45,22 @@ module.exports = [
}
]
},
{
"type": "section",
"capabilities": ["NOT_PLATFORM_APLITE", "NOT_PLATFORM_BASALT", "NOT_PLATFORM_CHALK"],
"items": [
{"type": "heading",
"defaultValue": "Health"
},
{
"type": "toggle",
"messageKey": "heartRateEnabled",
"defaultValue": true,
"label": "Show heart rate",
"description": "If enabled, the app shows the heart rate. If disabled, the app shows the number of steps taken today."
}
]
},
{
"type": "submit",
"defaultValue": "Save Settings"
Expand Down
4 changes: 2 additions & 2 deletions src/pkjs/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Import the Clay package
var Clay = require('pebble-clay');
// Load our Clay configuration file
var clayConfig = require('./config');
// Initialize Clay
var clayConfig = require('./config.js');
// Initialize Clay with Basalt as default platform
var clay = new Clay(clayConfig);

0 comments on commit de2df8a

Please sign in to comment.