Skip to content

Commit

Permalink
Initial code commit
Browse files Browse the repository at this point in the history
Basic Pebble App, uses JS to get data from web service
  • Loading branch information
hackingtype1 committed Mar 9, 2014
1 parent 7dc0ffd commit 7c5bc11
Show file tree
Hide file tree
Showing 16 changed files with 438 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*.lib
*.a

build/

# Shared objects (inc. Windows DLLs)
*.dll
*.so
Expand Down
11 changes: 11 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>cgm-pebble</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
pebble-cgm
==========

Basic pebble watch face (or app if you change the appinfo.json)

It does not require a companion app, other than the Pebble made app. It uses a JS file to grab data from an existing web service.

Please review the src/js/pebble-js-app.js file

Wherever the CGM data is, this file will need to "get" it. I use a web service (API) to get a response object that contains the info I use, but I've taken out the actual address of my svc.

You can dummy up the response to play around with the watch face.

Please check out Pebble's guides to get rolling,

and as with everything I have committed here: This is presented for educational purposes only, BE smart! don't make medical decisions based on data provided by this app.
69 changes: 69 additions & 0 deletions appinfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"uuid": "a4e66a45-f30d-4a13-9f0f-59343c6b23a9",
"shortName": "CGM",
"longName": "CGM",
"companyName": "HackingType1-CostikCare,LLC",
"versionCode": 2,
"versionLabel": "2.0.0",
"watchapp": {
"watchface": true
},
"appKeys": {
"delta":5,
"time":4,
"alert":3,
"readtime": 2,
"bg": 1,
"icon": 0
},
"resources": {
"media": [
{
"menuIcon": true,
"type": "png",
"name": "IMAGE_MENU_ICON",
"file": "img/logo.png"
},
{
"type": "png",
"name": "IMAGE_UP",
"file": "img/up.png"
},
{
"type": "png",
"name": "IMAGE_UPUP",
"file": "img/upup.png"
},
{
"type": "png",
"name": "IMAGE_UP45",
"file": "img/up45.png"
},
{
"type": "png",
"name": "IMAGE_FLAT",
"file": "img/flat.png"
},
{
"type": "png",
"name": "IMAGE_DOWN",
"file": "img/down.png"
},
{
"type": "png",
"name": "IMAGE_DOWNDOWN",
"file": "img/downdown.png"
},
{
"type": "png",
"name": "IMAGE_DOWN45",
"file": "img/down45.png"
},
{
"type": "png",
"name": "IMAGE_NONE",
"file": "img/none.png"
}
]
}
}
Binary file added resources/img/down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/down45.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/downdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/flat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/none.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/up45.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/upup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
270 changes: 270 additions & 0 deletions src/cgm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
#include "pebble.h"

static Window *window;

static TextLayer *bg_layer;
static TextLayer *readtime_layer;
static TextLayer *datetime_layer;
static TextLayer *message_layer;
static BitmapLayer *icon_layer;
static GBitmap *icon_bitmap = NULL;

static AppSync sync;

static uint8_t sync_buffer[256];
static char new_time[124];
static char last_bg[124];

static AppTimer *timer;

static const uint32_t const high[] = { 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100};
static const uint32_t const low[] = { 1000,100,1000,100,2000};

static const uint32_t const hypo[] = { 4900,200,4900 };
static const uint32_t const hyper[] = { 50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50,150,50 };

static const uint32_t const trend_high[] = { 200,200,1000,200,200,200,1000,200,200,200,1000 };
static const uint32_t const trend_low[] = { 2000,200,2000 };

static const uint32_t const alert[] = { 500,200,3000 };


enum CgmKey {
CGM_ICON_KEY = 0x0, // TUPLE_INT
CGM_BG_KEY = 0x1, // TUPLE_CSTRING
CGM_READTIME_KEY = 0x2, // TUPLE_CSTRING
CGM_ALERT_KEY = 0x3, // TUPLE_INT
CGM_TIME_NOW = 0x4, // TUPLE_CSTRING
CGM_DELTA_KEY = 0x5
};

static const uint32_t CGM_ICONS[] = {
RESOURCE_ID_IMAGE_UPUP, //0
RESOURCE_ID_IMAGE_UP, //1
RESOURCE_ID_IMAGE_UP45, //2
RESOURCE_ID_IMAGE_FLAT, //3
RESOURCE_ID_IMAGE_NONE, //4
RESOURCE_ID_IMAGE_DOWN45, //5
RESOURCE_ID_IMAGE_DOWN, //6
RESOURCE_ID_IMAGE_DOWNDOWN //7
};



static void sync_error_callback(DictionaryResult dict_error, AppMessageResult app_message_error, void *context) {
text_layer_set_text(datetime_layer, "--:--");
text_layer_set_text(message_layer, "Data: OFFLINE");

VibePattern pat = {
.durations = alert,
.num_segments = ARRAY_LENGTH(alert),
};

vibes_enqueue_custom_pattern(pat);
}

static void alert_handler(uint8_t alertValue)
{



APP_LOG(APP_LOG_LEVEL_DEBUG, "Alert code: %d", alertValue);

switch(alertValue){
//No alert
case 0:
break;

//Normal (new data, in range, trend okay)
case 1:
vibes_double_pulse();
break;

//Low
case 2: ;
VibePattern lowpat = {
.durations = low,
.num_segments = ARRAY_LENGTH(low),
};
vibes_enqueue_custom_pattern(lowpat);
break;

//High
case 3: ;
VibePattern highpat = {
.durations = high,
.num_segments = ARRAY_LENGTH(high),
};
vibes_enqueue_custom_pattern(highpat);
break;

//Hypo

//Hyper

//Trend Low

//Trend High

//Data Alert

}


}

static void sync_tuple_changed_callback(const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) {

switch (key) {

case CGM_ICON_KEY:
if (icon_bitmap) {
gbitmap_destroy(icon_bitmap);
}
icon_bitmap = gbitmap_create_with_resource(CGM_ICONS[new_tuple->value->uint8]);
bitmap_layer_set_bitmap(icon_layer, icon_bitmap);
break;

case CGM_BG_KEY:
text_layer_set_text(bg_layer, new_tuple->value->cstring);
strncpy(last_bg, new_tuple->value->cstring, 124);
break;

case CGM_READTIME_KEY:
strncpy(new_time, new_tuple->value->cstring, 124);
text_layer_set_text(readtime_layer, new_tuple->value->cstring);
break;

case CGM_TIME_NOW:
text_layer_set_text(datetime_layer, new_tuple->value->cstring);
break;

case CGM_ALERT_KEY:
alert_handler(new_tuple->value->uint8);
break;

case CGM_DELTA_KEY:
text_layer_set_text(message_layer, new_tuple->value->cstring);
break;
}

}

static void send_cmd(void) {

DictionaryIterator *iter;
app_message_outbox_begin(&iter);

if (iter == NULL) {
return;
}
static char *bgptr = last_bg;
static char *timeptr = new_time;

Tuplet alertval = TupletInteger(3, 0);
Tuplet bgVal = TupletCString(1, bgptr);
Tuplet lastTimeVal = TupletCString(2, timeptr);

dict_write_tuplet(iter, &alertval);
dict_write_tuplet(iter, &bgVal);
dict_write_tuplet(iter, &lastTimeVal);

dict_write_end(iter);

app_message_outbox_send();

}

static void timer_callback(void *data) {

send_cmd();
timer = app_timer_register(60000, timer_callback, NULL);

}

static void window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);

datetime_layer = text_layer_create(GRect(0, 100, 144, 22));
text_layer_set_text_color(datetime_layer, GColorBlack);
text_layer_set_background_color(datetime_layer, GColorWhite);
text_layer_set_font(datetime_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_text_alignment(datetime_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(datetime_layer));

icon_layer = bitmap_layer_create(GRect(84, 0, 60, 60));
layer_add_child(window_layer, bitmap_layer_get_layer(icon_layer));

bg_layer = text_layer_create(GRect(0, 5, 83, 68));
text_layer_set_text_color(bg_layer, GColorWhite);
text_layer_set_background_color(bg_layer, GColorClear);
text_layer_set_font(bg_layer, fonts_get_system_font(FONT_KEY_BITHAM_42_MEDIUM_NUMBERS));
text_layer_set_text_alignment(bg_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(bg_layer));

readtime_layer = text_layer_create(GRect(0, 48, 144, 115));
text_layer_set_text_color(readtime_layer, GColorWhite);
text_layer_set_background_color(readtime_layer, GColorClear);
text_layer_set_font(readtime_layer, fonts_get_system_font(FONT_KEY_BITHAM_42_LIGHT));
text_layer_set_text_alignment(readtime_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(readtime_layer));

message_layer = text_layer_create(GRect(0, 124, 144, 68));
text_layer_set_text_color(message_layer, GColorBlack);
text_layer_set_background_color(message_layer, GColorWhite);
text_layer_set_font(message_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_text_alignment(message_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(message_layer));

Tuplet initial_values[] = {
TupletInteger(CGM_ICON_KEY, (uint8_t) 4),
TupletCString(CGM_BG_KEY, ""),
TupletCString(CGM_READTIME_KEY, ""),
TupletInteger(CGM_ALERT_KEY, 0),
TupletCString(CGM_TIME_NOW, "loading..."),
TupletCString(CGM_DELTA_KEY, " ")
};

app_sync_init(&sync, sync_buffer, sizeof(sync_buffer), initial_values, ARRAY_LENGTH(initial_values),sync_tuple_changed_callback, sync_error_callback, NULL);

timer = app_timer_register(100, timer_callback, NULL);
}

static void window_unload(Window *window) {
app_sync_deinit(&sync);

if (icon_bitmap) {
gbitmap_destroy(icon_bitmap);
}
text_layer_destroy(datetime_layer);
text_layer_destroy(readtime_layer);
text_layer_destroy(bg_layer);
text_layer_destroy(message_layer);
bitmap_layer_destroy(icon_layer);
}

static void init(void) {
window = window_create();
window_set_background_color(window, GColorBlack);
window_set_fullscreen(window, true);
window_set_window_handlers(window, (WindowHandlers) {
.load = window_load,
.unload = window_unload
});

app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());

const bool animated = true;
window_stack_push(window, animated);
}

static void deinit(void) {
window_destroy(window);
}

int main(void) {
init();

app_event_loop();
deinit();
}
Loading

0 comments on commit 7c5bc11

Please sign in to comment.