NightScout openHAB Integration

As some of you are aware, the OAuth2 using just OH Rules and myopenhab.org came out of experiments trying to get integration between Dexcom and OH. Dexcom is a Continuous Glucose Monitor (CGM) used by diabetics, mostly Type 1/insulin dependent diabetics. For these users knowing their current blood sugar levels can be a matter of life and death. So having some sort of integration with one’s home automation can be useful where one can flash a light, send a message to an audio sync, or something like that in response to alarms.

This tutorial covers at a high level how to install and integrate a local instance of Nightscout, an open source alternative to Dexcom’s Clarity, with openHAB.

Nightscout


Nightscout is as much a community as it is a FOSS system. But the documentation and support is scattered and not always complete or easy to follow. The default set of instructions assumes you will be installing the Nightscout server and MongoDB database into the cloud. However, lots of folks like to run stuff like this locally. The following is what I did to set it up.

Out of scope of this tutorial is setting up and configuring the devices and apps that will publish the CGM readings into NightScout. We use xDrip+ on a new Google Pixel 3XL with a Dexcom G5. The G6 is on order. In both of these cases the CGM sensor can talk directly with the phone and the xDrip+ app will publish the readings to NightScout. Many other CGMs and apps are supported, including an app for iPhones and support for bridging from the sensor’s native source like Dexcom Clarity/Dexcom Share and NightScout.

NightScout itself consists of two main parts, the Mongo database and the Node.js based web app server. If one wants to access NightScout while not at home an nginx reverse proxy, ssh tunnel, or VPN connection from the phone reporting to NightScout and your LAN is required. This too is beyond the scope of this tutorial. If you don’t know how to do this securely I recommend using the default cloud based installation instructions. If you do so skip to the NightScout openHAB integration section.

The machine used to host this is an Ubuntu 18.04 Server running on a VM.

MongoDB

Install MongoDB Community Edition

I followed the official instructions for installing MongoDB documented here. It involves adding the repo and key for that repo and installing it using apt-get install mongodb-org. Then enabling and starting mongod using systemctl.

Create an admin user on MongoDB

Post installation the next thing I did was to create a user with the admin role in the admin database giving this new user the role userAdminAnyDatabase. I’ve done all of this in Ansible so I am not positive about these specific commands.

  • First run mongo to access the MongoDB shell.
    mongo
  • Switch to the admin database.
    use admin
  • Create a new user with the userAdminAnyDatabase role on the admin database.
db.createUser(
 {
   user: "foo",
   pwd: "bar",
   roles: [
     { role: "userAdminAnyDatabase", db: "admin" }
   ]
 }
 )
  • logout of the mongo shell

Full session.

rich@fenrir:~   mongo 
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("7b7b4d25-239f-4983-a7ba-57a2e3bab068") }
MongoDB server version: 4.0.3
> use admin
switched to db admin
> db.createUser(
... {
...   user: "foo",
...   pwd: "bar",
...   roles: [
...     { role: "userAdminAnyDatabase", db: "admin" }
...   ]
... }
... )
Successfully added user: {
        "user" : "foo",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}
> logout

Enable Authorization

Now that you have an admin user, enable authorization by adding the following to /etc/mongod.conf

security:
  authorization: enabled

Restart MongoDB

Now restart mongod.

sudo systemctl restart mongod

Nightscout

Create User and Database for Nightscout

We will be doing the following steps:

  • Log into mongo:
mongo -u foo -p bar --authenticationDatabase admin
  • Create a nightscout database
use nightscout
  • Create the nightscout user replacing “foo” with “nightscout”, “bar” with nightscout’s db password, the role with “dbOwner”, and “admin” with “nightscout”.
db.createUser(
 {
   user: "nightscout",
   pwd: "nightscoutpw",
   roles: [
     { role: "dbOwner", db: "nightscout" }
   ]
 }
 )

TODO Create a nightscout User to Run Under

The rest of these steps will run nightscout under your login user or root.

Install Nightscout Prerequisites

Using apt, install nodejs. At least on Ubuntu 18.04, this will also install npm. If it doesn’t for your system you may need to install it separately.

Fork and Clone the Nightscout Repo

The built in update mechanism depends on comparing your fork to the main Nightscout repo on GitHub. So if you want the ability to determine when it is time to upgrade automatically you must create a GitHub account, if you don’t have one already. Plus, this will let you contribute to OH. :wink:

Log into GitHub and navigate to the main nightscout repo.

Now fork the repo.

image

This should open you to a https://github.com/<your github username>/cgm-remote-monitor page which is a complete copy of everything in the “official” repo.

Now, back in your terminal and create /opt/cgm-remote-monitor.

sudo mkdir /opt/cgm-remote-monitor
sudo chown user:user /opt/cg,-remote-monitor

Where “user” is your login account.

Now change to /opt and clone your fork of the cgm-remote-monitor repo. Click on the green “Clone or download this repo” button. Make sure you have “Use https” selected if you haven’t set up ssh certs with GitHub and click the clipboard icon to copy the path to the repo to your clipboard.

cd /opt
git clone <ctrl>-v

Where -v is the paste from your clipboard the path to your github repo.

This will check out all the code that makes up Nightscout to the cgm-remote-monitor folder.

Install required libraries

NightScout requires the use of a lot of libraries. To automatically install them change to /opt/cgm-remote-monitor and run npm install.

cd /opt/cgm-remote-monitor
npm install

This may take a few minutes to complete.

Configuration

NightScout appears to be wholly configured through environment variables. To capture these environment variables and make them available only to the Nightscout process create a file my.env in the /opt/cgm-remote-monitor folder.

See the NightScout documentation and tutorials for the full list of supported variables. I used the following:

my.env

MONGO=mongodb://nightscout:nightscoutpw@localhost:27017/nightscout
API_SECRET=NIGHTSCOUTAPISECRET
ENABLE=careportal%20basal%20bwp%20iob%20cob%20cage%20sage%20iage
DISPLAY_UNITS=mg/dl
PORT=80
Parameter Purpose
MONGO The first line provides the MongoDB URL where the data gets saved. Note we are passing the database username and password (not the admin user and password). If you installed MongoDB on a different host change localhost to the appropriate hostname or IP address.
API_SECRET At least a 12 character (I think) secret that is required to enable access from new devices (kind of like that one time code you get when you have two-factor authentication enabled).
ENABLED List of add-ons that are enabled by default. I don’t know what any of these do yet, they appear to be the default set from many of the tutorials I’ve seen.
DISPLAY_UNITS I’m in the U.S. so …
PORT By default Nightscout runs on a different port. I’m not running behind a reverse proxy and have no other servers to conflict on this machine so I’m running on port 80.

Run NightScout

All of the very sparse tutorials I’ve found runs NightScout using pm2. I’m no Node.js developer so I can’t argue with any of the benefits or problems with this.

First we need to install pm2 and then run the server.

sudo npm install -g pm2
cd /opt/cgm-remote-monitor
sudo env $(cat my.env) pm2 start server.js

Congratulations, NightScout should be up and running. You can check on the status of the service using the command:

sudo pm2 status

TODO Configure

Configure the service to restart when the machine reboots.

Configure NightScout and Collector

This is outside the scope of this tutorial. Before NightScout will let you do anything with the tool it will require you to set up a profile. The profile will include all the stuff you are used to like carb conversion ratios and the like.

As I said previously, we are using the Android app xDrip+ as the collector. There is a setting in this app where the path to the MongoDB or the path to the NightScout REST API can be entered and it will start publishing CGM readings and other info like the battery level of the CGM sensor transmitter.

NightScout Integration with openHAB

Unlike all the pain I went through trying to get the Dexcom official API to work only to discover that the data is too old to do anything with, the NightScout API is refreshingly simple and easy to use. We only need simple HTTP get commands and the JSON transformation.

Prerequisites

  • HTTP Binding
  • JSON Transformation
  • Running NightScout

The NightScout API is documented here. We will only be demonstrating the entries/current.json endpoint. Working with the rest is an exercise left to the student.

Binding Config

We will use the HTTP binding in cache mode. Open $OH_CONF/service/html.cfg and add a new ID with a URL and upodateInterval. We will use an interval of three minutes which is half of the average of 6 minutes that I’m seeing records reported. YMMV.

nightscout.url=http://<hostname or IP address of nightscout server>/api/v1/entries/current.json
nightscout.updateInterval=180000

Items

You can go to that URL yourself in the browser to see all the available fields. The following Items shows how to get a few of them:

DateTime NS_LastReading_Time "Last Reading Time [%1$tm/%1$td %1$tH:%1$tM]" { http="<[nightscout:180000:JSONPATH($[0].dateString)]", expire="7m" }
Number NS_LastReading "Last Reading [%d] mg/dl"                            { http="<[nightscout:180000:JSONPATH($[0].sgv)]", expire="7m" }
String NS_Trend "Trend [%s]"                                               { http="<[nightscout:180000:JSONPATH($[0].direction)]", expire="7m" }

Sitemap

	Frame label="NightScout" {
		Text item=NS_LastReading_Time
		Text item=NS_LastReading
		Text item=NS_Trend
	}

Good luck!

4 Likes

Hi Rich,

great aproach. Our son (6 years) also suffers from diabetes type 1. He does not carry a mobile phone an uses the Medtronic Minimed 640g pump in combination with the Enlite CGM. So I build “on premise” solution without cloud.
Here are the details:

I’m running OpenHabian on a Raspberry with InfluxDB and Grafana. At night we connect an Android phone with the Contour Next 2,4 to den 640g. The Nightscout Uploader App and xDrip is running on the phone and the CGM data is written to InfluxDB.
With the help of the http binding collect the CGM values in an item.

http.cfg:

# configuration of the first cache item
glucose.url=http://localhost:8086/query?pretty=true&db=openhab_db&q=select%20value_mgdl%20from%20glucose%20ORDER%20BY%20time%20DESC%20limit%201
glucose.updateInterval=10000

glucose.items:

Switch Zucker_Timer "Zucker Timer" { expire="60m,command=OFF" }

Number ZuckerWert "CGM Wert [%d]"  { http="<[glucose:60000:JSONPATH($.results[*].series[*].values[0].[1])]" }

I use an internet radio (FS Internet Radio Binding) to wake us up if the glucose level rises above 200 or drops below 80

glucose.rules:

rule "Glucose_Alarm"
when 
    Item ZuckerWert changed 
then
    logInfo("Blutzucker", "Wert: "+ZuckerWert.state.toString)
    if(  ZuckerWert.state < 80 || ZuckerWert.state > 200  )  {
        logWarn("Blutzucker", "schlechter Wert Wert")
        if( Zucker_Timer.state != ON ) {
        logInfo("Blutzucker", "Radio an")
        RadioPower.sendCommand(ON)
        RadioPreset.sendCommand(3)
        RadioMode.sendCommand(0)
        RadioMute.sendCommand(OFF)
        RadioVolume.sendCommand(18)
        }
    }
end

rule "React on Radio Power (RadioPower) change/update"
when
    Item RadioPower changed from ON
then
    Zucker_Timer.sendCommand(ON)
end

When the radio is turned off, the expiry binding takes care that the radio is not turned on again right away.

The integration of the CGM into OpenHab works great and helps us monitoring the glucose level of our son in combination with getting enough sleep at night.

If someone is interested, I can can give more details on my configuration. For example I build a grafana dashboard to have a look at the current values and the values of the last 3 hours:

1 Like

I actually had to move to a Heroku deployment because FitBit broke the ability to get the data straight from xDrip and the watch face my wife uses (Glance) would only support HTTPS with s valid cert. It was way easier to set up a Heroku instance until FitBit gets their act together than to get Glance to work through my self hosted instance. But I will move back once FitBit fixes their bug.

We’re I to do it over again (and I just might) I’d set it up using Docker.

I’m glad to see others finding use or if this tutorial.

Hi Rich,

you mention

Unlike all the pain I went through trying to get the Dexcom official API to work only to discover that the data is too old to do anything with, the NightScout API is refreshingly simple and easy to use.

[Background: my son has type-1 and a Dexcom G6 sensor]

I’m interested in setting up something like this but I’d like to skip the NightScout parts (don’t want to have another system at home to support…) So what you are saying is that you get old values from Dexcom via it’s API, but fresh values from NightScout (that in it’s turn gets it from the Dexcom API?)

Or do I get a lot more benefits by using Nightscout?

My main interest (now) is to get the GCM data into Openhab for displaying/logging as well as having some alarms if the values get too low.

Firstly, you don’t have to maintain and manage or even run Nightscout at home. It took me quite a bit of trial and error to get a self hosted instance up and running. The normal instructions have you install it on Heroku or Azure and it is about as close to “push the button, have nightscout working” as it gets. I recently had to deploy my instance on Heroku because FitBit broke the ability to read data local to the phone (i.e. straight from xDrip) and the clock my wife uses, Glance, doesn’t really support locally hosted Nightscouts very easily.

Anyway, yes, Dexcom deliberately only gives you readings that are 90 minutes old or older. Except for historical analysis, you can’t use readings that old for anything useful.

The way we have it set up is not the only way one can set it up. We don’t use Dexcom at all. My wife uses xDrip on her phone which gets the readings from the G6 sensor directly. Then xDrip publishes the readings to Nightscout. Spike is the app that does this on iPhone I think. I also think that xDrip can get the data from Dexcom directly using Dexcom Follow (or whatever it’s called) but we don’t use that.

We prefer to have control over out own medical records rather than depending on a third party cloud service. We also know that the sensors last longer than the artificial limit of 10 days. With xDrip we can reset the sensor and get longer use out of them. With Nightscout you have your own history owned by you and not anyone else.

But you don’t have to abandon Dexcom entirely like we did I don’t think. I never really looked into that approach so can’t say for sure.

Also, in this context, the main benefit you get with Nightscout is that it’s the only way you can get any of the readings into openHAB. There is tons written about it and there are active Facebook groups for xDrip and Nightscout.

1 Like

xDrip can write data directly to a local InfluxDB. You don’t need Nightscout for that. My OpenHAB reads from that DB.
The only reason we use the NightScout uploader app is the connection to the Minimed 640g Pump.

That is correct and I shouldn’t have implied otherwise. I didn’t bring it up because if the questioner didn’t want to run an additional service that would apply to running Influxdbb or Mongodb too.