Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ A Pebble watchface to view data from a continuous glucose monitor in graph forma

![Screenshot](http://i.imgur.com/xefGk6A.png)

To install, enable Developer Mode in the Pebble app on your phone, then open [this pbw file][pbw] in the Pebble app.
To install, enable Developer Mode in the Pebble app on your phone, then download and open this pbw file https://github.com/woernsn/urchin-cgm/releases/download/v0.2.0/urchin-cgm.pbw in the Pebble app. For iPhone: Locate the downloaded .pwb file, and use the iPhone Share menu and pick the Pebble app to install Urchin.

Urchin CGM is an **U**nopinionated, **R**idiculously **C**onfigurable **H**uman **IN**nterface to your CGM. It's not released yet / in beta / a work-in-progress.

Expand All @@ -12,7 +12,7 @@ Urchin CGM is an **U**nopinionated, **R**idiculously **C**onfigurable **H**uman

* Open [the latest release][pbw] in your phone's browser, then open the file with the Pebble app to install.
* In the Pebble app on your phone, open the "Settings" screen for Urchin.
* To view data from a [Nightscout][cgm-remote-monitor] site, enter your site's URL.
* To view data from a [Nightscout][cgm-remote-monitor] site, enter your site's URL and token if authentication is enabled (see [Authentication Roles](http://www.nightscout.info/wiki/welcome/website-features/0-9-features/authentication-roles) for details).
* To view data from [Dexcom Share][dexcom-share], enter your username and password. (These credentials never leave your phone except to authorize with Dexcom's servers.)
* Optionally, personalize your watchface using the settings described below.

Expand Down
11 changes: 11 additions & 0 deletions config/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ <h3>DATA SOURCE:</h3>
</div>
</div>

<div class="item-container source-dependent" data-sources="nightscout">
<div class="item-container-header">Nightscout Token</div>
<div class="item-container-content">
<label class="item">
<div class="item-input-wrapper">
<input id="ns-token" class="item-input">
</div>
</label>
</div>
</div>

<div class="item-container source-dependent" data-sources="dexcom">
<div class="item-container-header">Share username</div>
<div class="item-container-content">
Expand Down
3 changes: 3 additions & 0 deletions config/js/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@
function populateValues(current) {
$('[name=dataSource][value=' + current['dataSource'] + ']').addClass('active');
$('#ns-url').val(current['nightscout_url'] || '');
$('#ns-token').val(current['nightscout_token'] || '');
$('[name=dexcomUsername]').val(current['dexcomUsername'] || '');
$('[name=dexcomPassword]').val(current['dexcomPassword'] || '');

Expand Down Expand Up @@ -690,6 +691,7 @@
mmol: mmol,
dataSource: $('[name=dataSource].active').attr('value'),
nightscout_url: $('#ns-url').val().replace(/\/$/, ''),
nightscout_token: $('#ns-token').val(),
dexcomUsername: $('[name=dexcomUsername]').val(),
dexcomPassword: $('[name=dexcomPassword]').val(),
hGridlines: tryParseInt($('#hGridlines').val()),
Expand Down Expand Up @@ -752,6 +754,7 @@
// redact PII
var current = JSON.parse(JSON.stringify(phoneConfig));
delete current['nightscout_url'];
delete current['nightscout_token'];
delete current['dexcomUsername'];
delete current['dexcomPassword'];
delete current['statusText'];
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "urchin-cgm",
"author": "Mark Wilson",
"version": "0.1.0",
"version": "0.2.0",
"keywords": ["pebble-app"],
"private": true,
"devDependencies": {
Expand Down Expand Up @@ -41,7 +41,7 @@
"prediction2": 11,
"prediction3": 12,
"predictionRecency": 13,

"mmol": 1,
"topOfGraph": 2,
"topOfRange": 3,
Expand Down
1 change: 1 addition & 0 deletions src/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ function app(Pebble, c) {
var clearCache = (
config.dataSource !== oldConfig.dataSource ||
config.nightscout_url !== oldConfig.nightscout_url ||
config.nightscout_token !== oldConfig.nightscout_token ||
config.dexcomUsername !== oldConfig.dexcomUsername ||
config.dexcomPassword !== oldConfig.dexcomPassword ||
maxSGVs > computeMaxSGVs(oldConfig) ||
Expand Down
1 change: 1 addition & 0 deletions src/js/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"DEFAULT_CONFIG" : {
"dataSource": "nightscout",
"nightscout_url" : "",
"nightscout_token" : "",
"dexcomUsername": "",
"dexcomPassword": "",
"mmol" : false,
Expand Down
26 changes: 16 additions & 10 deletions src/js/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,14 @@ var data = function(c, maxSGVCount) {
});
};

d.addTokenToUrl = function(url, token)
{
if (token != "")
return url + "&token=" + token;
}

d.getPebbleEndpoint = debounce(function(config) {
return d.getJSON(config.nightscout_url + '/pebble').then(function(pebbleData) {
return d.getJSON(d.addTokenToUrl(config.nightscout_url + '/pebble'), config.nightscout_token).then(function(pebbleData) {
if (pebbleData['bgs'] !== undefined && pebbleData['bgs'].length) {
return pebbleData['bgs'][0];
} else {
Expand Down Expand Up @@ -734,7 +740,7 @@ var data = function(c, maxSGVCount) {
} else {
start = new Date() - sgvCache.maxSecondsOld * 1000;
}
var url = config.nightscout_url + '/api/v1/entries/sgv.json?count=1000&find[date][$gt]=' + start;
var url = d.addTokenToUrl(config.nightscout_url + '/api/v1/entries/sgv.json?count=1000&find[date][$gt]=' + start, config.nightscout_token);
return d.getJSON(url).then(function(newEntries) {
return sgvCache.update(
filterKeys(newEntries, ['date', 'sgv', 'trend', 'direction', 'filtered', 'unfiltered', 'noise'])
Expand All @@ -744,7 +750,7 @@ var data = function(c, maxSGVCount) {

d.getTempBasals = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/treatments.json?find[eventType]=Temp+Basal&count=' + tempBasalCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/treatments.json?find[eventType]=Temp+Basal&count=' + tempBasalCache.maxSize, config.nightscout_token),
tempBasalCache,
'created_at',
['created_at', 'duration', 'absolute', 'percent']
Expand All @@ -753,23 +759,23 @@ var data = function(c, maxSGVCount) {

d.getLastUploaderBattery = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/devicestatus.json?find[$or][0][uploaderBattery][$exists]=true&find[$or][1][uploader][$exists]=true&count=' + uploaderBatteryCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/devicestatus.json?find[$or][0][uploaderBattery][$exists]=true&find[$or][1][uploader][$exists]=true&count=' + uploaderBatteryCache.maxSize, config.nightscout_token),
uploaderBatteryCache,
'created_at'
);
});

d.getLastCalibration = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/entries/cal.json?count=' + calibrationCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/entries/cal.json?count=' + calibrationCache.maxSize, config.nightscout_token),
calibrationCache,
'date'
);
});

d.getBolusHistory = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/treatments.json?find[insulin][$exists]=true&count=' + bolusCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/treatments.json?find[insulin][$exists]=true&count=' + bolusCache.maxSize, config.nightscout_token),
bolusCache,
'created_at',
['created_at', 'insulin']
Expand All @@ -778,23 +784,23 @@ var data = function(c, maxSGVCount) {

d.getOpenAPSStatusHistory = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/devicestatus.json?find[openaps][$exists]=true&count=' + openAPSStatusCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/devicestatus.json?find[openaps][$exists]=true&count=' + openAPSStatusCache.maxSize, config.nightscout_token),
openAPSStatusCache,
'created_at'
);
});

d.getLastLoopStatus = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/devicestatus.json?find[loop][$exists]=true&find[loop.failureReason][$not][$exists]=true&count=' + loopStatusCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/devicestatus.json?find[loop][$exists]=true&find[loop.failureReason][$not][$exists]=true&count=' + loopStatusCache.maxSize, config.nightscout_token),
loopStatusCache,
'created_at'
);
});

d.getLastLoopEnacted = debounce(function(config) {
return getUsingCache(
config.nightscout_url + '/api/v1/devicestatus.json?find[loop.enacted][$exists]=true&count=' + loopEnactedCache.maxSize,
d.addTokenToUrl(config.nightscout_url + '/api/v1/devicestatus.json?find[loop.enacted][$exists]=true&count=' + loopEnactedCache.maxSize, config.nightscout_token),
loopEnactedCache,
'created_at'
);
Expand All @@ -806,7 +812,7 @@ var data = function(c, maxSGVCount) {
// changes so infrequently that we can simply request it once per app load.
// (If the user updates their profile, they should restart the watchface.)
if (profileCache === undefined) {
profileCache = d.getJSON(config.nightscout_url + '/api/v1/profile.json');
profileCache = d.getJSON(d.addTokenToUrl(config.nightscout_url + '/api/v1/profile.json', config.nightscout_token));
}
return profileCache;
};
Expand Down
1 change: 1 addition & 0 deletions src/js/ga.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function track(data, trackingId, watchInfo, config) {
// redact PII
var current = JSON.parse(JSON.stringify(config));
delete current['nightscout_url'];
delete current['nightscout_token'];
delete current['dexcomUsername'];
delete current['dexcomPassword'];
delete current['statusText'];
Expand Down