/urchin-cgm

A graph of your CGM data on a Pebble watch.

Primary LanguageJavaScriptMIT LicenseMIT

A Pebble watchface to view data from a continuous glucose monitor in graph format, like this:

Screenshot

To install, enable Developer Mode in the Pebble app on your phone, then open this pbw file in the Pebble app.

Urchin CGM is an Unopinionated, Ridiculously Configurable Human INnterface to your CGM. It's not released yet / in beta / a work-in-progress.

Circle CI

Setup

  • Open the latest release 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 site, enter your site's URL.
  • To view data from 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.

Layout

The layout is one of the most Ridiculously Configurable aspects of Urchin. The settings page includes a handful of pre-set layouts to get you started:

Use one as a starting point to build your own watchface: reorder the elements, change heights and colors, toggle borders, move the icons...

Graph

Set the bounds and target range of the graph on your phone.

You can choose the shape and size of the points on the graph so that the glucose history is as long or as short as you want. To show up to 12 hours of BGs, plot the points super-thin or overlapping. For a "sparkline" view of the last hour, plot bigger points with more space in between.

Status bar content

The status bar can display content from a variety of sources:

  • Date - in whatever format you want. (e.g. Sat Oct 7)
  • Uploader battery level - if your Nightscout data comes from a wired rig/xDrip. (e.g. 36%)
  • Raw Dexcom readings - raw sensor readings plus noise level. (e.g. Cln 97 104 106)
  • Uploader battery, Dexcom raw - combination of the above two. (e.g. 36% Cln 97 104 106)
  • Active basal - NS Care Portal - the currently-active basal rate based on treatments in Nightscout Care Portal. If a temp basal is currently active, shows the difference from normal basal and how many minutes ago the temp basal began. (e.g. (19) 1.5U/h +0.6)
  • Insulin on board - this can be calculated from treatments entered manually in Nightscout Care Portal, or reported automatically from MiniMed Connect, Loop, or OpenAPS. (e.g. 2.3 U)
  • Insulin + carbs on board - same IOB as above plus carbs-on-board entered in Care Portal. (e.g. 2.3 U 31 g)
  • Loop status - status from the Loop iOS app -- predicted BG, IOB, COB, current temp basal, pump battery, pump reservoir, phone battery -- in whatever format you want. (e.g. 143 0.2U 13g 1.50, or 1.50U/h 0.2 U 13 g | 1.57v 109U 83%)
  • IOB and temp - OpenAPS - IOB and currently-active temp basal rate from the most recent OpenAPS status upload, or if the most recent status indicates failure, the time since that failure plus the time and IOB from the last successful status. (e.g. (2) 1.1U 1.9x13 or (4) -- | (+23) 2.2U)
  • Custom URL - text - if you want to summarize your data in a custom way.
  • Custom URL - JSON - show custom text, with support for a timestamp field to display recency (e.g. (3) your text).
  • Custom text - remind yourself whose glucose readings you're looking at, or leave a terse inspirational message.
  • Multiple - Up to 3 of the above, one on each line.

The recency indicator in the status bar is configurable. You can choose the format ((3), 3:, etc.) and the conditions under which it is shown (for example, "don't show the recency as long as it's fewer than 10 minutes old," or "don't show the status at all when it's more than 30 minutes old")

Pump data

If you are using Nightscout to track data from an insulin pump, you may choose to display bolus history (as ticks) and/or basal history (as a bar graph):

To enter pump data manually, you can use Nightcout Care Portal or the "CarePortal" Pebble app.

To upload pump data automatically, you can use RileyLink or Loop on iOS, or build an OpenAPS uploader.

Predictions

Like pump data, predicted future BGs can be plotted if you are using Loop on iOS, or OpenAPS with the Advanced Meal Assist (AMA) feature of the oref0 algorithm. For example, AMA generates three different projections assuming no carbs, normal carb absorption, and accelerated carb absorption.

What do the icons mean?

The data that you see on your watch travels like this: Sensor/Receiver -> Server -> Phone -> Pebble.

There is a problem with the Phone -> Pebble connection: it's been a while since your watch has been able to reach your phone. Maybe your phone is out of range. Maybe it's on airplane mode. Maybe you need to charge your phone.

There is a problem with the Server -> Phone connection: it's been a while since your phone has been able to reach the server. Maybe your phone's network connection is bad. Maybe your Nightscout server / Dexcom's server is down.

There is a problem with the Sensor/Receiver -> Server connection: the latest data on the server is old. Maybe there's a problem with your receiver or uploader. Maybe the sensor fell out.

When the watch fails to fetch data, a message describing the problem briefly appears in the graph.

Contributing

Contributions are welcome in the form of bugs and pull requests. To report a bug or provide feedback, please file an issue. To contribute code, please use the instructions below to build and test the watchface.

  • Install the Pebble SDK Tool.

  • Install and activate the Pebble SDK. As of this writing, the app is built with SDK 3.14, but later versions should work, too.

    pebble sdk install 3.14
    pebble sdk activate 3.14
    
  • Build and run the watchface with a command like:

    pebble build && pebble install --emulator basalt && pebble logs
    
  • The watchface will ask for settings from the "phone." Open the configuration page with this command and hit "save" in your browser (you'll need to do this only once):

    pebble emu-app-config --emulator basalt
    
  • At some point you'll want to install your revisions on your watch. Flip the "Enable Developer Connections" switch in the Pebble app on your phone, then:

    pebble install --phone <phone ip address>
    

Tips:

  • Testing the configuration page: For a default build, the contents of config/index.html and its dependencies are inlined and converted into a data URI. This data URI is rebuilt and included in the JS during a pebble build. When testing changes to the configuration page, however, it's easier if the emulator opens the un-inlined version. To build the watchface to open the HTML file, set BUILD_ENV to development:

    BUILD_ENV=development pebble build
    pebble install --emulator basalt
    pebble emu-app-config --emulator basalt
    
  • Debug logging: DEBUG=true enables extra logging from the watchface and JS:

    DEBUG=true pebble build
    pebble install --emulator basalt
    pebble logs --emulator basalt
    
  • Syntax checking: If you use Vim, I highly recommend using Syntastic to display syntax errors. On my OS X system running Pebble Tool v4.1.1, these lines make Syntastic aware of Pebble's header files and suppress warnings generated within those files:

    let g:syntastic_c_include_dirs = ['/Users/<user>/Library/Application Support/Pebble SDK/SDKs/current/sdk-core/pebble/aplite/include', 'build/aplite']
    let g:syntastic_c_remove_include_errors = 1
    
  • JavaScript errors: If you see a JavaScript error in the console, the line numbers will be reported relative to build/pebble-js-app.js, which is the concatenation of all files in src/js/**/*.js.

Testing

Since this software displays real-time health data, it is important to be able to verify that it works as expected.

The most effective method of integration testing I've found is to compare screenshots. This relies on ImageMagick to compute diffs. Screenshot tests and JavaScript unit tests are run automatically by CircleCI.

  • Install testing dependencies

    Install ImageMagick, then use pip to install Python testing dependencies:

    pip install -r requirements.txt --user
    
  • Use the live-reload tool

    This is the fastest way to test the watchface against specific configuration and data.

    Create a new test class in test/test_screenshots.py:

    class TestSomething(ScreenshotTest):
        config = {...}
        def sgvs(self):
            return [...]

    Build and install the watchface:

    pebble build && pebble install --emulator basalt
    

    Start the live-reload tool:

    . test/live_reload.sh TestSomething
    

    Whenever test/test_screenshots.py is modified, the config property of the test will be sent to the watchface. When the watchface makes a request for new data, the corresponding sgvs()/treatments()/etc. method on the test will be evaluated.

  • Run the screenshot test suite locally

    . test/do_screenshots.sh
    
  • Run an individual screenshot test locally

    . test/do_screenshots.sh -k TestName
    
  • Use the mock Nightscout server directly

    Start the server:

    MOCK_SERVER_PORT=5555 python test/server.py
    

    Build the watchface as usual:

    pebble build && pebble install --emulator basalt && pebble logs
    

    Use an editor to save mock data, send it to the server, verify it:

    vi sgv-data.json
    # ...edit mock data...
    
    # POST it for the server to store
    curl -d @sgv-data.json http://localhost:5555/set-sgv
    
    # Verify:
    curl http://localhost:5555/api/v1/entries/sgv.json
    
    # ("sgv" can be sgv, entries, treatments, devicestatus, or profile)
    

    Use the browser to configure the watchface:

    # Make sure you set the Nightscout host to "http://localhost:5555"
    pebble emu-app-config --emulator basalt
    
  • Run JavaScript unit tests locally

    These require Node. See the Mocha and Expect docs.

    cd test/js
    npm install
    npm test
    

To do:

  • High/low BG alerts
  • Stale data alerts
  • More color configurability
  • A fixed layout which supports Pebble Time Round
  • More dynamic sizing of content (e.g. bigger/smaller time and BG)
  • etc.

Disclaimer

This project is intended for educational and informational purposes only. It is not FDA approved and should not be used to make medical decisions. It is neither affiliated with nor endorsed by Dexcom.