Skip to content

Instantly share code, notes, and snippets.

@bewest

bewest/Makefile Secret

Forked from channemann/OpenAPS_Setup.md
Last active September 1, 2015 05:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bewest/d5f0fc68c0b9ac49c146 to your computer and use it in GitHub Desktop.
Save bewest/d5f0fc68c0b9ac49c146 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<title></title>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="http://lab.hakim.se/reveal-js//css/reveal.min.css"/>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
</style>
<link rel="stylesheet" href="http://lab.hakim.se/reveal-js//css/theme/simple.css" id="theme">
<!-- If the query includes 'print-pdf', include the PDF print sheet -->
<script>
if( window.location.search.match( /print-pdf/gi ) ) {
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://lab.hakim.se/reveal-js//css/print/pdf.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
}
</script>
<!--[if lt IE 9]>
<script src="http://lab.hakim.se/reveal-js//lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<div class="slides">
<section><section id="openaps-worksheet" class="titleslide slide level1"><h1>OpenAPS Worksheet</h1></section><section id="initial-build" class="slide level2">
<h1>Initial build</h1>
<p>See docs, <a href="http://openaps.gitbooks.io/building-an-open-artificial-pancreas-system/content/Setup/rpi.html">Section 3.1</a></p>
</section><section id="set-up-rpi-wifi" class="slide level2">
<h1>Set up RPi-wifi</h1>
<h3 id="notes-that-arent-included-there-..."><em>Notes that aren't included there ...</em></h3>
<p><code>$ wpa_passphrase &quot;&lt;my_SSID&gt;&quot; &quot;&lt;my_password&gt;&quot; &gt;&gt; /etc/wpa_supplicant/wpa_supplicant.conf</code></p>
<ul>
<li><p>Repeat as necessary to add all relevant WiFi networks</p></li>
<li><p>Use single quotes for SSID and PSK if an escape character is required</p></li>
</ul>
</section><section id="wifi-hardware" class="slide level2">
<h1>Wifi hardware</h1>
<p>Add <code>8192cu.conf</code> to <code>/etc/modprobe.d/</code>, Two solutions:</p>
<ol type="1">
<li>https://www.raspberrypi.org/forums/viewtopic.php?t=61665</li>
<li>https://learn.adafruit.com/adafruits-raspberry-pi-lesson-3-network-setup/test-and-configure#fixing-wifi-dropout-issues</li>
</ol>
</section><section id="timezone" class="slide level2">
<h1>Timezone</h1>
<p>Set up the timezone; make sure the RPi, pump, and dex are in-sync (and if you change one, you change them all)</p>
</section></section>
<section><section id="installing-openaps" class="titleslide slide level1"><h1>Installing openaps</h1></section><section id="installing-software" class="slide level2">
<h1>Installing software</h1>
<p>A number of dependencies can be installed via the package manager, <code>apt-get</code>.</p>
<p>Install git, dependencies, PyPi and <a href="https://github.com/openaps/openaps">OpenAPS</a></p>
<p><em>See docs, <a href="http://openaps.gitbooks.io/building-an-open-artificial-pancreas-system/content/Setup/openaps.html">Section 3.2</a></em></p>
<pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">sudo</span> apt-get git install python \
python-dev python-setuptools \
python-software-properties python-numpy
<span class="kw">sudo</span> easy_install -ZU openaps</code></pre>
</section><section id="configure-system-niceties" class="slide level2">
<h1>Configure system niceties</h1>
<pre class="sourceCode bash"><code class="sourceCode bash"><span class="kw">sudo</span> openaps-install-udev-rules
<span class="co">## **Enable tab completion for efficiency**</span>
<span class="kw">sudo</span> activate-global-python-argcomplete</code></pre>
<p>Log out, and back in.</p>
</section><section id="how-to-update" class="slide level2">
<h1>How to update</h1>
<p><strong>Update openaps (when required)</strong> <code>$ sudo easy_install -ZU openaps</code></p>
</section><section id="install-openaps-plugins" class="slide level2">
<h1>Install openaps plugins</h1>
<p><em>These installations assume the system is for usage, not for development. To install from source, see the individual plugin GitHub pages</em></p>
<h4 id="install-mmhistorytools-mmglucosetools-openaps-predict"><strong>Install <a href="https://github.com/loudnate/openaps-mmhistorytools">mmhistorytools</a></strong>, <a href="https://github.com/loudnate/openaps-mmglucosetools">mmglucosetools</a>, <a href="https://github.com/loudnate/openaps-predict">openaps-predict</a></h4>
<pre><code>sudo easy_install openapscontrib.mmhistorytools \
openapscontrib.mmglucosetools openapscontrib.predict</code></pre>
<h4 id="install-openaps-dose"><strong>Install openaps-dose</strong></h4>
<p>(not going to show how for this one quite yet)</p>
<h4 id="install-openaps-monitor"><strong>Install <a href="https://github.com/loudnate/openaps-monitor">openaps-monitor</a></strong></h4>
<p>(check the link for full installation instructions)</p>
</section></section>
<section><section id="configuring-openaps" class="titleslide slide level1"><h1>Configuring openaps</h1></section><section id="configure-names" class="slide level2">
<h1>Configure Names</h1>
<dl>
<dt>Openaps Name</dt>
<dd><input type="text" class="openaps_name updateable" data-replace="[$]myopenaps" name="openaps_name" value="" data-placeholder="pump"/>
</dd>
<dt>Pump Name</dt>
<dd><input type="text" name="pump_name" class="updateable" data-replace="[$]my_pump_name" value="" data-placeholder="pump"/>
</dd>
<dt>Pump Serial</dt>
<dd><input type="text" name="" class="updateable" data-replace="[$]my_pump_serial" value="" data-placeholder=""/>
</dd>
<dt>Dexcom name</dt>
<dd><input type="text" name="" class="updateable" data-replace="[$]my_dexcom_name" value="cgm" data-placeholder=""/> <strong>Add Dexcom CGM receiver as device (not required if using Medtronic CGM)</strong>
</dd>
</dl>
</section><section id="configure-openaps" class="slide level2">
<h1>Configure openaps</h1>
<p>Openaps manages a git database to store your data, and information about the provenance of that data at every step. Let's teach openaps about our situation.</p>
</section><section id="initialize-openaps-environment" class="slide level2">
<h1><strong>Initialize openaps environment</strong></h1>
<ul>
<li>Move into new openaps directory</li>
</ul>
<pre><code>openaps init $myopenaps
cd $myopenaps</code></pre>
<ul>
<li>Add cgm and pump devices</li>
</ul>
<pre><code>openaps device add $my_pump_name medtronic $my_pump_serial
openaps device add $my_dexcom_name dexcom</code></pre>
</section><section id="vendors-and-plugins" class="slide level2">
<h1>Vendors and plugins</h1>
<p>A <strong><code>vendor</code></strong> is an implementation of some <code>device</code>. Third party plugins can implement the <code>vendor</code> protocol to implement new kinds of devices for openaps. A <strong><code>device</code></strong> is the name we give to actual hardware we own that we would like the implementation to work with. Openaps knows about Medtronic and Dexcom devices; the community has provided several new implementations to help manage data.</p>
</section><section id="adding-plugins" class="slide level2">
<h1>Adding plugins</h1>
<p><strong>Add openaps plugins (first as vendors, then as devices)</strong></p>
</section><section id="configure-plugin-names" class="slide level2">
<h1>Configure plugin names</h1>
<table>
<tr>
<td>
Munge name
</td>
<td>
<input type="text" name="" class="updateable" data-replace="[$]munge" value="munge" data-placeholder=""/>
</td>
</tr>
<tr>
<td>
Glucose Tool name
</td>
<td>
<input type="text" name="" class="updateable" data-replace="[$]glucose" value="glucose" data-placeholder=""/>
</td>
</tr>
<tr>
<td>
Predict name
</td>
<td>
<input type="text" name="" class="updateable" data-replace="[$]predict" value="predict" data-placeholder=""/>
</td>
</tr>
<tr>
<td>
Dose name
</td>
<td>
<input type="text" name="" class="updateable" data-replace="[$]dose" value="dose" data-placeholder=""/>
</td>
</tr>
</table>
</section><section id="configure-plugins" class="slide level2">
<h1>Configure plugins</h1>
<pre><code>$ openaps vendor add openapscontrib.mmhistorytools
$ openaps device add $munge mmhistorytools
$ openaps vendor add openapscontrib.mmglucosetools
$ openaps device add $glucose mmglucosetools
$ openaps vendor add openapscontrib.predict
$ openaps device add $predict predict
$ openaps vendor add openapscontrib.dose
$ openaps device add $dose dose</code></pre>
</section><section id="checking-device-configuration" class="slide level2">
<h1>Checking device configuration</h1>
<p><strong>Check that the devices are all added properly</strong></p>
<pre><code>$ openaps device show
medtronic://pump
dexcom://cgms
mmhistorytools://munge
mmglucosetools://glucose
predict://predict
dose://dose</code></pre>
<p>where the strings after the // are the names you used for <code>$my_pump_name</code>, <code>$my_dexcom_name</code>, et ceter</p>
</section></section>
<section><section id="use-openaps" class="titleslide slide level1"><h1><strong>use</strong> openaps</h1></section><section id="openaps-use" class="slide level2">
<h1><code>openaps use</code></h1>
<p>Once devices are configured, you can <strong><code>use</code></strong> them. <code>openaps use</code> allows using any of the device's vendor operations on the device, right from the commandline.</p>
</section><section id="chat-with-a-pump" class="slide level2">
<h1>Chat with a pump</h1>
<p><strong>Check that you can talk with your pump</strong></p>
<p><code>$ openaps use $my_pump_name model</code></p>
<p>should return something like:</p>
<p><code>&quot;723&quot;</code></p>
</section><section id="chat-with-cgm" class="slide level2">
<h1>Chat with CGM</h1>
<p><strong>Check that you can talk with your dex</strong></p>
<p><code>$ openaps use $my_dexcom_name iter_glucose 1</code></p>
<p>should return something like:</p>
<pre><code>[
{
&quot;trend_arrow&quot;: &quot;FLAT&quot;,
&quot;system_time&quot;: &quot;2015-08-23T21:45:29&quot;,
&quot;display_time&quot;: &quot;2015-08-23T13:46:21&quot;,
&quot;glucose&quot;: 137
}
]</code></pre>
</section><section id="configure-reports" class="slide level2">
<h1>Configure reports</h1>
<p><strong>Add a whole bunch of reports</strong></p>
<p>It's a good idea to check each one out after adding by invoking it and checking the output. For example, after the first one below (with your dex connected), run <code>$ openaps report invoke recent_glucose.json</code>, which will create a file called <code>recent_glucose.json</code>. Then, run <code>$ cat recent_glucose.json</code> and you should see a file with your most recent glucose values.</p>
</section><section id="also-a-few-notes" class="slide level2">
<h1>Also, a few notes:</h1>
<ul>
<li>The items in &lt;angle_brackets&gt; are the names you assigned when adding the devices; don't actually use the &lt; &gt;</li>
<li>If you are using a Medtronic CGM, the first report should use the <code>$my_pump_name</code> device instead of the <code>$my_dexcom_name</code> device; the <code>iter_glucose_hours</code> function is common to those devices</li>
<li>For the first two, the number <code>6</code> is used; you should use a number greater than or equal to your insulin duration, plus a few hours (I have an insulin duration of 3 hours, so I use 3 + 3 = 6 hours to cover longer square boluses)</li>
<li>We know that <code>read_insulin_sensitivies</code> is mispelled; this is done because it is mispelled in the openaps toolset, so we decided to keep it consistent</li>
<li>When you are testing the ones near the bottom (that take in a file), make sure you have run the previous reports to generate those input files</li>
</ul>
</section><section id="add-reports" class="slide level2">
<h1>Add reports</h1>
<pre><code>$ openaps report add recent_glucose.json JSON $my_dexcom_name iter_glucose_hours 6
$ openaps report add recent_history.json JSON $my_pump_name iter_pump_hours 6
$ openaps report add read_clock.json JSON $my_pump_name read_clock
$ openaps report add read_battery_status.json JSON $my_pump_name read_battery_status
$ openaps report add read_settings.json JSON $my_pump_name read_settings
$ openaps report add read_carb_ratios.json JSON $my_pump_name read_carb_ratios
$ openaps report add read_selected_basal_profile.json JSON $my_pump_name read_seleced_basal_profile
$ openaps report add read_insulin_sensitivies.json JSON $my_pump_name read_insulin_sensitivies
$ openaps report add read_bg_targets.json JSON $my_pump_name read_bg_targets
$ openaps report add read_status.json JSON $my_pump_name read_status
$ openaps report add clean_glucose.json JSON $glucose clean recent_glucose.json
$ openaps report add reconcile_history.json JSON $munge reconcile clean_hisory.json
$ openaps report add resolve_history.json JSON $munge resolve reconcile_history.json
$ openaps report add clean_history.json JSON $munge clean recent_history.json
$ openaps report add normalized_history.json JSON $munge normalize \
resolved_history.json
--basal-profile basal.json
--zero-at read_clock.json
$ openaps report add predict_glucose.json JSON $predict glucose \
normalize_history.json \
recent_glucose.json \
--settings read_settings.json \
--insulin-sensitivities read_insulin_sensitivies.json \
--carb-ratios read_carb_ratios.json
$ openaps report add predict_glucose_without_future_basal.json JSON $predict glucose \
normalize_history.json \
recent_glucose.json \
--settings read_settings.json \
--insulin-sensitivities read_insulin_sensitivies.json \
--carb-ratios read_carb_ratios.json
--basal-dosing-end read_clock.json
$ openaps report add recommended_dose.json JSON $dose recommend \
--resolved-history resolve_history.json \
--settings read_settings.json \
--clock read_clock.json \
--bg-targets read_bg_targets.json \
--insulin-sensitivities read_insulin_sensitivies.json \
--basal-profile read_selected_basal_profile.json \
--predict-glucose-without-basal predict_glucose_without_future_basal.json
$ openaps report add set_dose.json JSON $my_pump_name deliver recommended_dose.json </code></pre>
<p>Did you remember to test all of those reports (in order)? Good!</p>
</section><section id="add-aliases" class="slide level2">
<h1>Add aliases</h1>
<p><strong>Add aliases</strong></p>
<p>Aliases are a way to gather a number of openaps commands into a single, easy-to-exute command. Instead of having to run all of the above reports individually, you can instead make logical groupings and run them together. For example, after adding the first alias below (<code>refresh</code>), you can simply run <code>$ openaps refresh</code> and it will execute the constituent reports in order.</p>
</section><section id="alias-examples" class="slide level2">
<h1>Alias examples</h1>
<p>Add the following aliases:</p>
<pre><code>$ openaps alias add refresh &quot;report invoke read_settings.json read_bg_targets.json read_insulin_sensitivies.json read_selected_basal_profile.json read_carb_ratios.json&quot;
$ openaps alias add update &quot;report invoke read_status.json read_battery_status.json read_clock.json recent_glucose.json recent_history.json&quot;
$ openaps alias add munge &quot;report invoke clean_glucose.json clean_history.json reconcile_history.json resolve_history.json normalize_history.json&quot;
$ openaps alias add predict &quot;report invoke predict_glucose.json predict_glucose_without_future_basal.json&quot;
$ openaps alias add dose &quot;report invoke recommended_dose.json set_dose.json&quot;</code></pre>
</section><section id="testing-alias" class="slide level2">
<h1>Testing alias</h1>
<p>Just like you did with the reports, go ahead and test each of these aliases to make sure the execute properly. For example,</p>
<p><code>$ openaps refresh</code></p>
<p>should return:</p>
<pre><code>pump://JSON/read_settings/read_settings.json
reporting read_settings.json
pump://JSON/read_bg_targets/read_bg_targets.json
reporting read_bg_targets.json
pump://JSON/read_insulin_sensitivies/read_insulin_sensitivies.json
reporting read_insulin_sensitivies.json
pump://JSON/read_selected_basal_profile/read_selected_basal_profile.json
reporting read_selected_basal_profile.json
pump://JSON/read_carb_ratios/read_carb_ratios.json
reporting read_carb_ratios.json</code></pre>
</section><section id="inspecting-openaps.ini" class="slide level2">
<h1>Inspecting <code>openaps.ini</code></h1>
<p>This completes the setup of the openaps.ini file, which resides in your <code>$myopenaps</code> directory. Go ahead and take a look using <code>$ cat openaps.ini</code>.</p>
</section><section id="set-up-your-loop" class="slide level2">
<h1>Set up your loop</h1>
<p>Make a new directory in your top-level directory (which is probably something like <code>/home/pi</code>) called <code>/bin</code>.</p>
<pre><code>$ cd
$ mkdir bin
$ cd bin</code></pre>
<p>We will put three files in the <code>/bin</code> directory: one to initialize the web server, one that power cycles the CareLink stick to make sure it continues to run, and one that defines the loop. For each of these, make sure and replace <code>$myopenaps</code> with the directory name you chose for your OpenAPS instance. I'm assuming here that it is in <code>/home/pi/$myopenaps</code>, but make sure to check and use the correct full pathname.</p>
</section><section id="set-up-start-web" class="slide level2">
<h1>Set up start-web</h1>
<p><strong>Set up start-web</strong></p>
<p>start-web.sh</p>
<pre><code>cd /home/pi/openaps-monitor
screen -d -A -S openaps -m python monitor.py /home/pi/hannemannopenaps
cd -
cd /home/pi/$myopenaps
openaps refresh
cd -</code></pre>
</section><section id="set-up-fix-stick" class="slide level2">
<h1>Set up fix-stick</h1>
<p><strong>Set up fix-stick</strong></p>
<p>fix-stick.sh</p>
<pre><code>#!/bin/sh
echo &quot;Power-cycling USB to fix dead Carelink stick&quot;
sleep 0.1
echo 0 &gt; /sys/devices/platform/bcm2708_usb/buspower
sleep 1
echo 1 &gt; /sys/devices/platform/bcm2708_usb/buspower
sleep 2</code></pre>
</section><section id="set-up-loop-shell-script" class="slide level2">
<h1>Set up loop shell script</h1>
<p><strong>Set up loop shell script</strong></p>
<p>every-five.sh</p>
<pre><code>#!/bin/bash
fuser $(python -m decocare.scan) &amp;&amp; exit 1
cd /home/pi/$myopenaps
openaps update &amp;&amp; \
openaps munge &amp;&amp; \
openaps predict &amp;&amp; \
openaps dose || (python -m decocare.stick $(python -m decocare.scan) &gt; /dev/null &amp;&amp; echo &quot;Stick OK&quot; 1&gt;&amp;2 || ~/fix-stick.sh 1&gt;&amp;2)
git push 2&gt;&amp;1
cd -</code></pre>
</section><section id="configure-scripts" class="slide level2">
<h1>Configure scripts</h1>
<p>While still in <code>/home/pi/bin</code>, run:</p>
<p><code>$ chmod a+xr ./*</code></p>
<p>(I forget exactly what this does ... changed the color of the .sh files when doing <code>ls</code>, I believe, so it registered them or something?)</p>
<p>Also, do this:</p>
<p><code>$ sudo apt-get install screen</code></p>
<p>I think this is for the <code>openaps-monitor</code> to function properly.</p>
</section><section id="set-up-cron-job" class="slide level2">
<h1>Set up CRON job</h1>
<p><strong>Set up CRON job</strong></p>
<p>This file goes in your top-level directory (again, probably <code>/home/pi</code>). It tells the OS when to run the scripts. In this case, it is running <code>start-web.sh</code> upon reboot and <code>every-five.sh</code> every five minutes (surprise). <code>every-five.sh</code> calls <code>fix-stick.sh</code> to make sure the CareLink stick is still ticking.</p>
<pre><code># Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use &#39;*&#39; in these fields (for &#39;any&#39;).#
# Notice that tasks will be started based on the cron&#39;s system
# daemon&#39;s notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# m h dom mon dow command
*/5 * * * * /home/pi/bin/every-five.sh &gt; /dev/null
@reboot /home/pi/bin/start-web.sh &gt; /dev/null</code></pre>
</section><section id="done" class="slide level2">
<h1>done</h1>
<p>Reboot.</p>
</section></section>
</div>
</div>
<script src="http://lab.hakim.se/reveal-js//lib/js/head.min.js"></script>
<script src="http://lab.hakim.se/reveal-js//js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: 'solarized', // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'http://lab.hakim.se/reveal-js//lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'http://lab.hakim.se/reveal-js//plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'http://lab.hakim.se/reveal-js//plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } },
// { src: 'http://lab.hakim.se/reveal-js//plugin/search/search.js', async: true, condition: function() { return !!document.body.classList; }, }
// { src: 'http://lab.hakim.se/reveal-js//plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
]});
</script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js">
</script>
<script type="text/javascript">
Reveal.addEventListener('ready', function (ev) {
console.log('ev', ev);
$('code').each(function (i, elem) {
elem = $(elem);
var clone = elem.clone(true);
elem.addClass('original');
elem.attr('id', 'original_' + i);
elem.css('display', 'none');
clone.addClass('show');
clone.attr('id', 'show_' + i);
elem.after(clone);
});
});
function do_update (ev) {
// console.log('updated', ev);
var target = $(ev.target);
console.log(ev.data);
ev.data[target.data('replace')] = target.val( );
if (target.is('.updateable')) {
$('code.original').each(function (i, elem) {
elem = $(elem);
var show = $('#show_' + i);
// console.log(show);
var text = elem.text( );
for (var x in ev.data) {
text = text.replace(new RegExp(x, 'g'), ev.data[x]);
}
show.text(text);
});
}
}
var replacements = { 'status': 'ok' };
$('.slide').on('click change', ':input, button', replacements, do_update);
</script>
</body>
</html>
#!/bin/bash
# **Install Python packages, system wide**
apt-get install git python python-dev python-setuptools python-software-properties python-numpy
## **Install PyPi and [OpenAPS](https://github.com/openaps/openaps)**
easy_install -ZU openaps
## **Install udev-rules**
openaps-install-udev-rules
## **Enable tab completion for efficiency**
activate-global-python-argcomplete
## **Update openaps (when required)**
easy_install -ZU openaps
## Install openaps plugins
#### **Install [mmhistorytools](https://github.com/loudnate/openaps-mmhistorytools)**
easy_install openapscontrib.mmhistorytools
#### **Install [mmglucosetools](https://github.com/loudnate/openaps-mmglucosetools)**
easy_install openapscontrib.mmglucosetools
#### **Install [openaps-predict](https://github.com/loudnate/openaps-predict)**
easy_install openapscontrib.predict
#### **Install openaps-dose**
#### **Install [openaps-monitor](https://github.com/loudnate/openaps-monitor)**
openaps --version
all: index.html
index.html: OpenAPS_Setup.md script.html
pandoc -A script.html -V theme=solarized --variable revealjs-url:http://lab.hakim.se/reveal-js/ -s -t revealjs OpenAPS_Setup.md -o index.html

OpenAPS Worksheet

Initial build

See docs, Section 3.1

Set up RPi-wifi

Notes that aren't included there ...

$ wpa_passphrase "<my_SSID>" "<my_password>" >> /etc/wpa_supplicant/wpa_supplicant.conf

  • Repeat as necessary to add all relevant WiFi networks

  • Use single quotes for SSID and PSK if an escape character is required

Wifi hardware

Add 8192cu.conf to /etc/modprobe.d/, Two solutions:

  1. https://www.raspberrypi.org/forums/viewtopic.php?t=61665
  2. https://learn.adafruit.com/adafruits-raspberry-pi-lesson-3-network-setup/test-and-configure#fixing-wifi-dropout-issues

Timezone

Set up the timezone; make sure the RPi, pump, and dex are in-sync (and if you change one, you change them all)

Installing openaps

Installing software

A number of dependencies can be installed via the package manager, apt-get.

Install git, dependencies, PyPi and OpenAPS

See docs, Section 3.2

sudo apt-get git install python \
     python-dev python-setuptools \
     python-software-properties python-numpy
sudo easy_install -ZU openaps

Configure system niceties

sudo openaps-install-udev-rules
## **Enable tab completion for efficiency**
sudo activate-global-python-argcomplete

Log out, and back in.

How to update

Update openaps (when required) $ sudo easy_install -ZU openaps

Install openaps plugins

These installations assume the system is for usage, not for development. To install from source, see the individual plugin GitHub pages

sudo easy_install openapscontrib.mmhistorytools \
   openapscontrib.mmglucosetools openapscontrib.predict

Install openaps-dose

(not going to show how for this one quite yet)

(check the link for full installation instructions)

Configuring openaps

Configure Names

Openaps Name :

Pump Name :

Pump Serial :

Dexcom name : Add Dexcom CGM receiver as device (not required if using Medtronic CGM)

Configure openaps

Openaps manages a git database to store your data, and information about the provenance of that data at every step. Let's teach openaps about our situation.

Initialize openaps environment

  • Move into new openaps directory
openaps init $myopenaps
cd $myopenaps
  • Add cgm and pump devices
openaps device add $my_pump_name medtronic $my_pump_serial
openaps device add $my_dexcom_name dexcom

Vendors and plugins

A vendor is an implementation of some device. Third party plugins can implement the vendor protocol to implement new kinds of devices for openaps. A device is the name we give to actual hardware we own that we would like the implementation to work with. Openaps knows about Medtronic and Dexcom devices; the community has provided several new implementations to help manage data.

Adding plugins

Add openaps plugins (first as vendors, then as devices)

Configure plugin names

Munge name
Glucose Tool name
Predict name
Dose name

Configure plugins

$ openaps vendor add openapscontrib.mmhistorytools
$ openaps device add $munge mmhistorytools
$ openaps vendor add openapscontrib.mmglucosetools
$ openaps device add $glucose mmglucosetools
$ openaps vendor add openapscontrib.predict
$ openaps device add $predict predict
$ openaps vendor add openapscontrib.dose
$ openaps device add $dose dose

Checking device configuration

Check that the devices are all added properly

$ openaps device show
medtronic://pump
dexcom://cgms
mmhistorytools://munge
mmglucosetools://glucose
predict://predict
dose://dose

where the strings after the // are the names you used for $my_pump_name, $my_dexcom_name, et ceter

use openaps

openaps use

Once devices are configured, you can use them. openaps use allows using any of the device's vendor operations on the device, right from the commandline.

Chat with a pump

Check that you can talk with your pump

$ openaps use $my_pump_name model

should return something like:

"723"

Chat with CGM

Check that you can talk with your dex

$ openaps use $my_dexcom_name iter_glucose 1

should return something like:

[
  {
    "trend_arrow": "FLAT", 
    "system_time": "2015-08-23T21:45:29", 
    "display_time": "2015-08-23T13:46:21", 
    "glucose": 137
  }
]

Configure reports

Add a whole bunch of reports

It's a good idea to check each one out after adding by invoking it and checking the output. For example, after the first one below (with your dex connected), run $ openaps report invoke recent_glucose.json, which will create a file called recent_glucose.json. Then, run $ cat recent_glucose.json and you should see a file with your most recent glucose values.

Also, a few notes:

  • The items in <angle_brackets> are the names you assigned when adding the devices; don't actually use the < >
  • If you are using a Medtronic CGM, the first report should use the $my_pump_name device instead of the $my_dexcom_name device; the iter_glucose_hours function is common to those devices
  • For the first two, the number 6 is used; you should use a number greater than or equal to your insulin duration, plus a few hours (I have an insulin duration of 3 hours, so I use 3 + 3 = 6 hours to cover longer square boluses)
  • We know that read_insulin_sensitivies is mispelled; this is done because it is mispelled in the openaps toolset, so we decided to keep it consistent
  • When you are testing the ones near the bottom (that take in a file), make sure you have run the previous reports to generate those input files

Add reports

$ openaps report add recent_glucose.json JSON $my_dexcom_name iter_glucose_hours 6
$ openaps report add recent_history.json JSON $my_pump_name iter_pump_hours 6
$ openaps report add read_clock.json JSON $my_pump_name read_clock
$ openaps report add read_battery_status.json JSON $my_pump_name read_battery_status
$ openaps report add read_settings.json JSON $my_pump_name read_settings
$ openaps report add read_carb_ratios.json JSON $my_pump_name read_carb_ratios
$ openaps report add read_selected_basal_profile.json JSON $my_pump_name read_seleced_basal_profile
$ openaps report add read_insulin_sensitivies.json JSON $my_pump_name read_insulin_sensitivies
$ openaps report add read_bg_targets.json JSON $my_pump_name read_bg_targets
$ openaps report add read_status.json JSON $my_pump_name read_status
$ openaps report add clean_glucose.json JSON $glucose clean recent_glucose.json
$ openaps report add reconcile_history.json JSON $munge reconcile clean_hisory.json
$ openaps report add resolve_history.json JSON $munge resolve reconcile_history.json
$ openaps report add clean_history.json JSON $munge clean recent_history.json
$ openaps report add normalized_history.json JSON $munge normalize \
	resolved_history.json
	--basal-profile basal.json
	--zero-at read_clock.json
$ openaps report add predict_glucose.json JSON $predict glucose \
        normalize_history.json \
	recent_glucose.json \
	--settings read_settings.json \
	--insulin-sensitivities read_insulin_sensitivies.json \
	--carb-ratios read_carb_ratios.json
$ openaps report add predict_glucose_without_future_basal.json JSON $predict glucose \
        normalize_history.json \
	recent_glucose.json \
	--settings read_settings.json \
	--insulin-sensitivities read_insulin_sensitivies.json \
	--carb-ratios read_carb_ratios.json
	--basal-dosing-end read_clock.json
$ openaps report add recommended_dose.json JSON $dose recommend \
	--resolved-history resolve_history.json \
	--settings read_settings.json \
	--clock read_clock.json \
	--bg-targets read_bg_targets.json \
	--insulin-sensitivities read_insulin_sensitivies.json \
	--basal-profile read_selected_basal_profile.json \
	--predict-glucose-without-basal predict_glucose_without_future_basal.json
$ openaps report add set_dose.json JSON $my_pump_name deliver recommended_dose.json		

Did you remember to test all of those reports (in order)? Good!

Add aliases

Add aliases

Aliases are a way to gather a number of openaps commands into a single, easy-to-exute command. Instead of having to run all of the above reports individually, you can instead make logical groupings and run them together. For example, after adding the first alias below (refresh), you can simply run $ openaps refresh and it will execute the constituent reports in order.

Alias examples

Add the following aliases:

$ openaps alias add refresh "report invoke read_settings.json read_bg_targets.json read_insulin_sensitivies.json read_selected_basal_profile.json read_carb_ratios.json"
$ openaps alias add update "report invoke read_status.json read_battery_status.json read_clock.json recent_glucose.json recent_history.json"
$ openaps alias add munge "report invoke clean_glucose.json clean_history.json reconcile_history.json resolve_history.json normalize_history.json"
$ openaps alias add predict "report invoke predict_glucose.json predict_glucose_without_future_basal.json"
$ openaps alias add dose "report invoke recommended_dose.json set_dose.json"

Testing alias

Just like you did with the reports, go ahead and test each of these aliases to make sure the execute properly. For example,

$ openaps refresh

should return:

pump://JSON/read_settings/read_settings.json
reporting read_settings.json
pump://JSON/read_bg_targets/read_bg_targets.json
reporting read_bg_targets.json
pump://JSON/read_insulin_sensitivies/read_insulin_sensitivies.json
reporting read_insulin_sensitivies.json
pump://JSON/read_selected_basal_profile/read_selected_basal_profile.json
reporting read_selected_basal_profile.json
pump://JSON/read_carb_ratios/read_carb_ratios.json
reporting read_carb_ratios.json

Inspecting openaps.ini

This completes the setup of the openaps.ini file, which resides in your $myopenaps directory. Go ahead and take a look using $ cat openaps.ini.

Set up your loop

Make a new directory in your top-level directory (which is probably something like /home/pi) called /bin.

$ cd
$ mkdir bin
$ cd bin

We will put three files in the /bin directory: one to initialize the web server, one that power cycles the CareLink stick to make sure it continues to run, and one that defines the loop. For each of these, make sure and replace $myopenaps with the directory name you chose for your OpenAPS instance. I'm assuming here that it is in /home/pi/$myopenaps, but make sure to check and use the correct full pathname.

Set up start-web

Set up start-web

start-web.sh

cd /home/pi/openaps-monitor
screen -d -A -S openaps -m python monitor.py /home/pi/hannemannopenaps
cd -
cd /home/pi/$myopenaps
openaps refresh
cd -

Set up fix-stick

Set up fix-stick

fix-stick.sh

#!/bin/sh
echo "Power-cycling USB to fix dead Carelink stick"
sleep 0.1
echo 0 > /sys/devices/platform/bcm2708_usb/buspower
sleep 1
echo 1 > /sys/devices/platform/bcm2708_usb/buspower
sleep 2

Set up loop shell script

Set up loop shell script

every-five.sh

#!/bin/bash
fuser $(python -m decocare.scan) && exit 1
cd /home/pi/$myopenaps
openaps update && \
openaps munge && \
openaps predict && \
openaps dose || (python -m decocare.stick $(python -m decocare.scan) > /dev/null && echo "Stick OK" 1>&2 || ~/fix-stick.sh 1>&2)
git push 2>&1

cd -

Configure scripts

While still in /home/pi/bin, run:

$ chmod a+xr ./*

(I forget exactly what this does ... changed the color of the .sh files when doing ls, I believe, so it registered them or something?)

Also, do this:

$ sudo apt-get install screen

I think this is for the openaps-monitor to function properly.

Set up CRON job

Set up CRON job

This file goes in your top-level directory (again, probably /home/pi). It tells the OS when to run the scripts. In this case, it is running start-web.sh upon reboot and every-five.sh every five minutes (surprise). every-five.sh calls fix-stick.sh to make sure the CareLink stick is still ticking.

# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# m  h dom mon dow   command
 */5 *  *   *   *    /home/pi/bin/every-five.sh > /dev/null
@reboot		     /home/pi/bin/start-web.sh > /dev/null

done

Reboot.

<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js">
</script>
<script type="text/javascript">
Reveal.addEventListener('ready', function (ev) {
console.log('ev', ev);
$('code').each(function (i, elem) {
elem = $(elem);
var clone = elem.clone(true);
elem.addClass('original');
elem.attr('id', 'original_' + i);
elem.css('display', 'none');
clone.addClass('show');
clone.attr('id', 'show_' + i);
elem.after(clone);
});
});
function do_update (ev) {
// console.log('updated', ev);
var target = $(ev.target);
console.log(ev.data);
ev.data[target.data('replace')] = target.val( );
if (target.is('.updateable')) {
$('code.original').each(function (i, elem) {
elem = $(elem);
var show = $('#show_' + i);
// console.log(show);
var text = elem.text( );
for (var x in ev.data) {
text = text.replace(new RegExp(x, 'g'), ev.data[x]);
}
show.text(text);
});
}
}
var replacements = { 'status': 'ok' };
$('.slide').on('click change', ':input, button', replacements, do_update);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment