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
2 changes: 2 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mmcsv
===========
This is the ORIGINAL README file for Ben West's mmcsv repo. It should all still work if needed, hence I've left this in
Instructions on mmcsv640g will go up soon :-)

Scraper and Parser for Medtronic pump, cgb and connected bg meter data.

Expand Down
8 changes: 0 additions & 8 deletions Release.md

This file was deleted.

36 changes: 36 additions & 0 deletions config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#! /bin/bash
# Initialising Carelink Automation
# Proof of concept ONLY - 640g csv to NightScout
#
# ****************************************************************************************
# USER SPECIFIC Working Directories - Please enter your details here
# ****************************************************************************************
# ExamplePath='/c/Data/Path'
# NB NO SPACES anywhere here, unless you know what you're doing please - Welcome to Shell Scripting :-)
Mmcsv640gPath='/c/Users/matt/Nightscout/csv/mmcsv' #Installation Directory for mmscv640g stack
CSVDataPath='/c/Users/matt/AutoCSV' # The directory you want to throw all the data around in
DownloadPath='/c/Users/matt/Downloads' # Where your CSV file downloaded from CareLink will appear (without any IMPORTANT CSV files in it!)
NodejsPath='/c/Program Files/nodejs' # Where Nodejs installed on your system
MousePath='/c/Users/matt/Nightscout' #Where MiniMouseMacro is installed
# ****************************************************************************************
# USER SPECIFIC Variables - Please enter your values here
# ****************************************************************************************
api_secret_hash='2ce212ef676099da17ec5aff64db0c83bf3f7b4f' # This is the SHA-1 Hash of your API-SECRET string - eg "ASANEXAMPLE1" is transformed into...
your_nightscout='https://yourwebsite.azurewebsites.net' #'https://something.azurewebsites.net'
gap_mins=5 # max time to wait for CSV download. Suggest 5 or 10 minutes and always start higher
gap_mins_delay=0 # use strict time for each upload cycle (if >0) or don't wait to minimise latency (0)
# ****************************************************************************************
# USER SPECIFIC Uploader Info - Please enter your values here
# ****************************************************************************************
uploader=1 #Firefox + Selenium (0) or .NET uploader (1): default is 1 from version 0.8 onwards
CareLinkURL='https://carelink.minimed.eu' #CareLink site, .eu or .com
CareLinkUsername='user' #CareLink Username
CareLinkPassword='password' #CareLink Password
# ****************************************************************************************
# AUTOMATICALLY GENERATED Variables - No need to edit these yourself
# ****************************************************************************************
carelink_dateformat='dd/MM/yyyy' # Website date format from CareLink
carelink_customerID='' # Customer ID from CareLink
carelink_locale='en_GB' # Locale from CareLink
carelink_timestamp='DD/MM/YYTHH:mm:ss' # CSV time and date format for CareLink locale
#
86 changes: 86 additions & 0 deletions depreciated/Selenium_Upload_Example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="https://carelink.minimed.eu/" />
<title>Upload_Only</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Upload_Only</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/patient/signout.do</td>
<td></td>
</tr>
<tr>
<td>waitForPageToLoad</td>
<td></td>
<td></td>
</tr>
<tr>
<td>open</td>
<td>/patient/entry.jsp?bhcp=1</td>
<td></td>
</tr>
<tr>
<td>waitForPageToLoad</td>
<td></td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>id=j_username</td>
<td>YOURUSERNAME</td>
</tr>
<tr>
<td>type</td>
<td>id=j_password</td>
<td>YOURPASSWORD</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>id=loginButton</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>link=Upload Data from My Device</td>
<td></td>
</tr>
<tr>
<td>waitForPageToLoad</td>
<td></td>
<td></td>
</tr>
<tr>
<td>pause</td>
<td>180000</td>
<td>180000</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>id=toReports</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>link=Data Export (CSV)</td>
<td></td>
</tr>
<tr>
<td>selectWindow</td>
<td>null</td>
<td></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>css=#reportPicker11 &gt; span.reportNav_right &gt; #reportNav_button</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
5 changes: 5 additions & 0 deletions depreciated/mmcsv640g.mmmacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1 | 612 | 663 | 2999 | Left Click Down

2 | 612 | 663 | 104 | Left Click Release
3 | 610 | 610 | 2999 | Left Click Down
4 | 610 | 610 | 104 | Left Click Release
45 changes: 32 additions & 13 deletions lib/parsers/basal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,46 @@
module.exports = function configure (utils) {
function parse (row, callback) {

var details = utils.details(utils.select(row, 'Raw-Values') || '');
if (!details.RATE) {
return callback( );
}
// Using careportal "Temp" basal to add values of SCHEDULED basal change (not perfect I know...)
// Using this will over-ride your basal PROFILE set in Nightscout...
//'Temp Basal Start': { bg: true, duration: true, percent: true, absolute: true }
// Requires careportal plugin in Nightscout
// Just picking out SCHEDULED basal changes here
// eventTime: 'YYYY-MM-DDTHH:mm:ss.SSSZ'
// Note Temp Basal event type (not start / end)
// Raw Values are BasalProfileStart at start / on
// Absolute values (units per hour) only in this script
// Duration is preset to 24 hours - ie tees this up until next rate is spotted...
// NOT used at present...

var details = utils.pluck(row, ['Raw-Type', 'Timestamp']);
var value = details['Raw-Type'];

var values = utils.details(utils.select(row, 'Raw-Values') || '');

if (value == 'BasalProfileStart') {
var data = {
scheduleName: details.PATTERN_NAME,
value: parseFloat(details.RATE),
type: 'basal-rate-change',
deliveryType: 'scheduled',
deviceTime: utils.reformatISO(utils.select(row, 'Timestamp'))
};
value: values.RATE,
eventType: 'Temp Basal',
duration: parseInt(1440),
absolute: parseFloat(values.RATE),
enteredBy: 'CSV',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
} ;

return callback(null, data);
}

function isValid (data) {
return (!isNaN(data.value) && data.type == 'basal-rate-change');
return data.value || false;
}

var pattern = /BasalProfileStart/g;
var pattern = /ChangeProgrammedTempBasal|ChangeTempBasal/g;
var stream = utils.pipeline(utils.split( ), utils.map(parse), utils.validator(isValid));
var parser = { pattern: pattern, stream: stream, parse: parse };
return parser;

}
55 changes: 55 additions & 0 deletions lib/parsers/basal_temp_absolute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

module.exports = function configure (utils) {
function parse (row, callback) {

//'Temp Basal Start': { bg: true, duration: true, percent: true, absolute: true }
// 'Temp Basal End': { bg: true}
// Adapted to push in temporary basals
// Requires careportal plugin in Nightscout
// Currently just picking out manual temp basals, not smartguard (PLGM) - see plgm.js
// eventTime: 'YYYY-MM-DDTHH:mm:ss.SSSZ'
// Note Temp Basal event type (not start / end)
// Raw Values are ChangeProgrammedTempBasalPercent at start / on
// Raw Values are ChangeTempBasalPercent at off /cancelation
// Absolute change only in this script

var details = utils.pluck(row, ['Raw-Type', 'Timestamp']);
var value = details['Raw-Type'];

var values = utils.details(utils.select(row, 'Raw-Values') || '');

if (value == 'ChangeProgrammedTempBasal') {
var data = {
value: value,
eventType: 'Temp Basal',
duration: parseInt((values.DURATION)/(60.*1000.)),
absolute: parseFloat(values.RATE),
enteredBy: 'CSV',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
}
else {
var data = {
value: value,
eventType: 'Temp Basal',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
};

return callback(null, data);
}

function isValid (data) {
return data.value || false;
}

var pattern = /ChangeProgrammedTempBasal|ChangeTempBasal/g;
var stream = utils.pipeline(utils.split( ), utils.map(parse), utils.validator(isValid));
var parser = { pattern: pattern, stream: stream, parse: parse };
return parser;

}
57 changes: 57 additions & 0 deletions lib/parsers/basal_temp_percent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

module.exports = function configure (utils) {
function parse (row, callback) {

//'Temp Basal Start': { bg: true, duration: true, percent: true, absolute: true }
// 'Temp Basal End': { bg: true}
// Adapted to push in temporary basals
// Requires careportal plugin in Nightscout
// Currently just picking out manual temp basals, not smartguard (PLGM) - see plgm.js
// eventTime: 'hh:mm', 'YYYY-MM-DDTHH:mm:ss.SSSZ'
// Medtronic % change is % of original ie 0% = 0units, 150% = 1.5 units / hr on 1.0 unit/hr basal
// Nightscout % change is % change ie 0% = 1unit/hr (no change), -100% = 0 units/hr; convert from Medtronic to NS by -100
// Note Temp Basal event type (not start / end)
// Raw Values are ChangeProgrammedTempBasalPercent at start / on
// Raw Values are ChangeTempBasalPercent at off /cancelation
// Percent change only in this script

var details = utils.pluck(row, ['Raw-Type', 'Timestamp']);
var value = details['Raw-Type'];

var values = utils.details(utils.select(row, 'Raw-Values') || '');

if (value == 'ChangeProgrammedTempBasalPercent') {
var data = {
value: value,
eventType: 'Temp Basal',
duration: parseInt((values.DURATION)/(60.*1000.)),
percent: parseInt(values.PERCENT_OF_RATE - 100),
enteredBy: 'CSV',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
}
else {
var data = {
value: value,
eventType: 'Temp Basal',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
};

return callback(null, data);
}

function isValid (data) {
return data.value || false;
}

var pattern = /ChangeProgrammedTempBasalPercent|ChangeTempBasalPercent/g;
var stream = utils.pipeline(utils.split( ), utils.map(parse), utils.validator(isValid));
var parser = { pattern: pattern, stream: stream, parse: parse };
return parser;

}
34 changes: 34 additions & 0 deletions lib/parsers/battery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

module.exports = function configure (utils) {
function parse (row, callback) {

// Dummy - Not used at the mo...

// eventTime: 'hh:mm', 'YYYY-MM-DDTHH:mm:sssZ'

var details = utils.pluck(row, ['Prime Type', 'Timestamp']);
var value = details['Prime Type'];

if (value == 'Fill Canula') {
var data = {
value: value,
eventType: 'Insulin Change',
enteredBy: 'CSV',
dateString: utils.reformatISO(details['Timestamp']),
created_at: utils.reformatCPTime(details['Timestamp']),
date: utils.reformatDate(details['Timestamp'])
}
};

return callback(null, data);
}

function isValid (data) {
return data.value || false;
}

var pattern = /Prime/g;
var stream = utils.pipeline(utils.split( ), utils.map(parse), utils.validator(isValid));
var parser = { pattern: pattern, stream: stream, parse: parse };
return parser;
}
Loading