Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show warnings if the display cannot be written to, but dont completel… #17

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
158 changes: 85 additions & 73 deletions index.js
Original file line number Diff line number Diff line change
@@ -3,98 +3,110 @@
/*jslint node: true */
/*jslint esversion: 6 */

'use strict';
"use strict";


const i2c = require('i2c-bus');
const path = require('path');
const pngparse = require('pngparse');
const extend = require('extend');
const i2c = require("i2c-bus");
const path = require("path");
const pngparse = require("pngparse");
const extend = require("extend");

var i2cBus = i2c.openSync(1);

// setup the display
var displayConfig = require('./config/display.json');
displayConfig.i2cBus = i2cBus;
var display = require('./lib/display/ssd1306')(displayConfig);

// display the logo
pngparse.parseFile('./static/unicorn.png', function(err, image) {
if(err)
throw err
display.clear();
display.oled.drawBitmap(image.data);
});

// setup battery voltage monitor
var voltageConfig = require('./config/voltage.json')
voltageConfig.i2cBus = i2cBus
var voltage = require('./lib/voltage/voltage')(voltageConfig)

// setup socket server for external commands
var batteryConfig = require('./config/battery.json')
var socketServer = require('./lib/socket-server/socket-server')({
voltage: voltage,
battery: batteryConfig
})
socketServer
.on('error', (err) => {
console.log('socket-server error: ', err.reason)
})
.on('warning', (warn) => {
console.log('socket-server warning: ', warn.reason)
})

var voltage = setupVoltageMonitor();

// setup the display
try {
var displayConfig = setupDisplayConfig();
var display = setupDisplay();
setupMenus();
} catch (error) {
console.warn("Warning: Could not set up display", error);
}

// setup the menus
var buttonsConfig = require('./config/buttons.json');
var menuConfig = {
menuFile: process.cwd() + path.sep + './config/menus/menu.json', // file path for the menu definition
onChange: showMenu, // method to call when menu changes
menuSettings: {
displayLines: displayConfig.displayLines - 1, // one line is used for menu title
moreUpLabel: " ^ ^ ^",
moreDownLabel: " v v v"
}
};
var hidMenu = require('./lib/hid-menu/hid-menu')(buttonsConfig, menuConfig);
function setupDisplayConfig() {
var displayConfig = require("./config/display.json");
displayConfig.i2cBus = i2cBus;
return displayConfig;
}

// configure menu events
hidMenu
.on('nothing', function () {
})
.on('showvoltage', function () {
voltage()
.then(function (v) {
function setupDisplay() {
var display = require("./lib/display/ssd1306")(displayConfig);
// display the logo
pngparse.parseFile("./static/unicorn.png", function(err, image) {
if (err) throw err;
display.clear();
display.write('Voltage: ' + v);
})
.catch(function (e) {
console.log(e.toString());
display.oled.drawBitmap(image.data);
});
})
.on('menu_changed', function () {
showMenu(hidMenu);
})
.on('showoutput', function (err, stdout, stderr) {
display.clear();
display.write(stdout);
});
return display;
}

function setupMenus() {
var buttonsConfig = require("./config/buttons.json");
var menuConfig = {
menuFile: process.cwd() + path.sep + "./config/menus/menu.json",
onChange: showMenu,
menuSettings: {
displayLines: displayConfig.displayLines - 1,
moreUpLabel: " ^ ^ ^",
moreDownLabel: " v v v"
}
};
var hidMenu = require("./lib/hid-menu/hid-menu")(buttonsConfig, menuConfig);
// configure menu events
hidMenu
.on("nothing", function() {})
.on("showvoltage", function() {
voltage()
.then(function(v) {
display.clear();
display.write("Voltage: " + v);
})
.catch(function(e) {
console.log(e.toString());
});
})
.on("menu_changed", function() {
showMenu(hidMenu);
})
.on("showoutput", function(err, stdout, stderr) {
display.clear();
display.write(stdout);
});
}

function setupVoltageMonitor() {
var voltageConfig = require("./config/voltage.json");
voltageConfig.i2cBus = i2cBus;
var voltage = require("./lib/voltage/voltage")(voltageConfig);
// setup socket server for external commands
var batteryConfig = require("./config/battery.json");
var socketServer = require("./lib/socket-server/socket-server")({
voltage: voltage,
battery: batteryConfig
});
socketServer
.on("error", err => {
console.log("socket-server error: ", err.reason);
})
.on("warning", warn => {
console.log("socket-server warning: ", warn.reason);
});
return voltage;
}

// display the current menu on the display
function showMenu(menu) {
display.clear();
var text = '';
var text = "";

var p = menu.getParentSelect();
text += p ? '[' + p.label + ']\n' : '';
text += p ? "[" + p.label + "]\n" : "";
var c = menu.getCurrentSelect();
menu.getActiveMenu().forEach(function (m) {
text += (m.selected ? '>' : ' ') + m.label + '\n';
menu.getActiveMenu().forEach(function(m) {
text += (m.selected ? ">" : " ") + m.label + "\n";
});

// console.log(text);
// console.log(text);
display.write(text);
}
329 changes: 195 additions & 134 deletions scripts/status.js
Original file line number Diff line number Diff line change
@@ -1,194 +1,255 @@

'use strict';

const i2c = require('i2c-bus');
const path = require('path');
const extend = require('extend');
var os = require('os');
var fs = require('fs');
var font = require('oled-font-5x7');
var i2cBus = i2c.openSync(1);

// Rounds value to 'digits' decimal places
function round(value, digits)
{
if (! digits) { digits = 0; }
function round(value, digits) {
if (!digits) {
digits = 0;
}
var scale = Math.pow(10, digits);
return Math.round(value * scale) / scale;
}

function convert_bg(value, profile)
{
if (profile != null && profile.out_units == "mmol/L")
{
function convert_bg(value, profile) {
if (profile != null && profile.out_units == "mmol/L") {
return round(value / 18, 1).toFixed(1);
}
else
{
} else {
return Math.round(value);
}
}

function stripLeadingZero(value)
{
function stripLeadingZero(value) {
var re = /^(-)?0+(?=[\.\d])/;
return value.toString().replace( re, '$1');
return value.toString().replace(re, "$1");
}

// setup the display
var displayConfig = require('/root/src/openaps-menu/config/display.json');
displayConfig.i2cBus = i2cBus;
var display = require('/root/src/openaps-menu/lib/display/ssd1306')(displayConfig);

//Parse all the .json files we need
try {
var profile = JSON.parse(fs.readFileSync("/root/myopenaps/settings/profile.json"));
} catch (e) {
setupDisplay();
} catch (error) {
console.warn("Warning: Could not set up display", error);
}

function setupDisplay() {
var displayConfig = require("/root/src/openaps-menu/config/display.json");
displayConfig.i2cBus = i2cBus;
var display = require("/root/src/openaps-menu/lib/display/ssd1306")(
displayConfig
);

//Parse all the .json files we need
try {
var profile = JSON.parse(
fs.readFileSync("/root/myopenaps/settings/profile.json")
);
} catch (e) {
// Note: profile.json is optional as it's only needed for mmol conversion for now. Print an error, but not return
console.error("Could not parse profile.json: ", e);
}
try {
var batterylevel = JSON.parse(fs.readFileSync("/root/myopenaps/monitor/edison-battery.json"));
} catch (e) {
}
try {
var batterylevel = JSON.parse(
fs.readFileSync("/root/myopenaps/monitor/edison-battery.json")
);
} catch (e) {
console.error("Could not parse edison-battery.json: ", e);
}
}

if(batterylevel) {
if (batterylevel) {
//Process and display battery gauge
display.oled.drawLine(115, 57, 127, 57, 1); //top
display.oled.drawLine(115, 63, 127, 63, 1); //bottom
display.oled.drawLine(115, 57, 115, 63, 1); //left
display.oled.drawLine(127, 57, 127, 63, 1); //right
display.oled.drawLine(114, 59, 114, 61, 1); //iconify
var batt = Math.round(127 - (batterylevel.battery / 10));
var batt = Math.round(127 - batterylevel.battery / 10);
display.oled.fillRect(batt, 58, 126, 62, 1); //fill battery gauge
}
}

//Create and render clock
function displayClock() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
display.oled.setCursor(83, 57);
display.oled.writeString(font, 1, hour+":"+min, 1, true);
}
//Create and render clock
function displayClock() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
display.oled.setCursor(83, 57);
display.oled.writeString(font, 1, hour + ":" + min, 1, true);
}

displayClock();
displayClock();

//bg graph
display.oled.drawLine(5, 51, 5, 21, 1);
display.oled.drawLine(5, 51, 127, 51, 1);
//targets high and low
display.oled.drawLine(2, 30, 5, 30, 1);
display.oled.drawLine(2, 40, 5, 40, 1);
//bg graph
display.oled.drawLine(5, 51, 5, 21, 1);
display.oled.drawLine(5, 51, 127, 51, 1);
//targets high and low
display.oled.drawLine(2, 30, 5, 30, 1);
display.oled.drawLine(2, 40, 5, 40, 1);

try {
var suggested = JSON.parse(fs.readFileSync("/root/myopenaps/enact/suggested.json"));
} catch (e) {
try {
var suggested = JSON.parse(
fs.readFileSync("/root/myopenaps/enact/suggested.json")
);
} catch (e) {
return console.error("Could not parse suggested.json: ", e);
}
try {
var bg = JSON.parse(fs.readFileSync("/root/myopenaps/monitor/glucose.json"));
} catch (e) {
}
try {
var bg = JSON.parse(
fs.readFileSync("/root/myopenaps/monitor/glucose.json")
);
} catch (e) {
return console.error("Could not parse glucose.json: ", e);
}
//render BG graph
var numBGs = (suggested.predBGs != undefined) ? (72) : (120); //fill the whole graph with BGs if there are no predictions
var date = new Date();
var zerotime = date.getTime() - ((numBGs * 5) * 600);
var zero_x = numBGs + 5;
for (var i = 0; i < numBGs; i++) {
}
//render BG graph
var numBGs = suggested.predBGs != undefined ? 72 : 120; //fill the whole graph with BGs if there are no predictions
var date = new Date();
var zerotime = date.getTime() - numBGs * 5 * 600;
var zero_x = numBGs + 5;
for (var i = 0; i < numBGs; i++) {
if (bg[i] != null) {
var x = 2 + zero_x + Math.round(((((bg[i].date - zerotime)/1000)/60)/5));
var y = Math.round( 21 - ( ( bg[i].glucose - 250 ) / 8 ) );
//left and right boundaries
if ( x < 5 ) x = 5;
if ( x > 127 ) x = 127;
//upper and lower boundaries
if ( y < 21 ) y = 21;
if ( y > 51 ) y = 51;
display.oled.drawPixel([x, y, 1]);
// if we have multiple data points within 3m, look further back to fill in the graph
if ( bg[i-1] && bg[i-1].date - bg[i].date < 200000 ) {
numBGs++;
}
var x = 2 + zero_x + Math.round((bg[i].date - zerotime) / 1000 / 60 / 5);
var y = Math.round(21 - (bg[i].glucose - 250) / 8);
//left and right boundaries
if (x < 5) x = 5;
if (x > 127) x = 127;
//upper and lower boundaries
if (y < 21) y = 21;
if (y > 51) y = 51;
display.oled.drawPixel([x, y, 1]);
// if we have multiple data points within 3m, look further back to fill in the graph
if (bg[i - 1] && bg[i - 1].date - bg[i].date < 200000) {
numBGs++;
}
}
}
}

//render predictions, only if we have them
if (suggested.predBGs != undefined) {
//render line between actual BG and predicted
x = zero_x + 3;
display.oled.drawLine(x, 51, x, 21, 1);
//render predictions
var predictions = [suggested.predBGs.IOB, suggested.predBGs.ZT, suggested.predBGs.UAM, suggested.predBGs.COB];
for (i = 0; i <= 48; i++) {
//render predictions, only if we have them
if (suggested.predBGs != undefined) {
//render line between actual BG and predicted
x = zero_x + 3;
display.oled.drawLine(x, 51, x, 21, 1);
//render predictions
var predictions = [
suggested.predBGs.IOB,
suggested.predBGs.ZT,
suggested.predBGs.UAM,
suggested.predBGs.COB
];
for (i = 0; i <= 48; i++) {
x++;
for(var n = 0; n <=3 && (predictions[n] != undefined); n++) {
y = Math.round( 21 - ( (predictions[n][i] - 250 ) / 8) );
//right boundary
if ( x > 127 ) x = 127;
//upper and lower boundaries
if ( y < 21 ) y = 21;
if ( y > 51 ) y = 51;
display.oled.drawPixel([x, y, 1]);
for (var n = 0; n <= 3 && predictions[n] != undefined; n++) {
y = Math.round(21 - (predictions[n][i] - 250) / 8);
//right boundary
if (x > 127) x = 127;
//upper and lower boundaries
if (y < 21) y = 21;
if (y > 51) y = 51;
display.oled.drawPixel([x, y, 1]);
}
}
}
}
//calculate timeago for BG
var startDate = new Date(bg[0].date);
var endDate = new Date();
var minutes = Math.round(( (endDate.getTime() - startDate.getTime()) / 1000) / 60);
if (bg[0].delta) {
//calculate timeago for BG
var startDate = new Date(bg[0].date);
var endDate = new Date();
var minutes = Math.round(
(endDate.getTime() - startDate.getTime()) / 1000 / 60
);
if (bg[0].delta) {
var delta = Math.round(bg[0].delta);
} else if (bg[1] && bg[0].date - bg[1].date > 200000 ) {
} else if (bg[1] && bg[0].date - bg[1].date > 200000) {
var delta = Math.round(bg[0].glucose - bg[1].glucose);
} else if (bg[2] && bg[0].date - bg[2].date > 200000 ) {
} else if (bg[2] && bg[0].date - bg[2].date > 200000) {
var delta = Math.round(bg[0].glucose - bg[2].glucose);
} else if (bg[3] && bg[0].date - bg[3].date > 200000 ) {
} else if (bg[3] && bg[0].date - bg[3].date > 200000) {
var delta = Math.round(bg[0].glucose - bg[3].glucose);
} else {
} else {
var delta = 0;
}
}

//display BG number, add plus sign if delta is positive
display.oled.setCursor(0,57);
if (delta >= 0) {
display.oled.writeString(font, 1, "BG:"+convert_bg(bg[0].glucose, profile)+"+"+stripLeadingZero(convert_bg(delta, profile))+" "+minutes+"m", 1, true);
} else {
display.oled.writeString(font, 1, "BG:"+convert_bg(bg[0].glucose, profile)+""+stripLeadingZero(convert_bg(delta, profile))+" "+minutes+"m", 1, true);
}
//display BG number, add plus sign if delta is positive
display.oled.setCursor(0, 57);
if (delta >= 0) {
display.oled.writeString(
font,
1,
"BG:" +
convert_bg(bg[0].glucose, profile) +
"+" +
stripLeadingZero(convert_bg(delta, profile)) +
" " +
minutes +
"m",
1,
true
);
} else {
display.oled.writeString(
font,
1,
"BG:" +
convert_bg(bg[0].glucose, profile) +
"" +
stripLeadingZero(convert_bg(delta, profile)) +
" " +
minutes +
"m",
1,
true
);
}

try {
var temp = JSON.parse(fs.readFileSync("/root/myopenaps/monitor/last_temp_basal.json"));
} catch (e) {
try {
var temp = JSON.parse(
fs.readFileSync("/root/myopenaps/monitor/last_temp_basal.json")
);
} catch (e) {
return console.error("Could not parse last_temp_basal.json: ", e);
}

//calculate timeago for status
var stats = fs.statSync("/root/myopenaps/monitor/last_temp_basal.json");
startDate = new Date(stats.mtime);
endDate = new Date();
minutes = Math.round(( (endDate.getTime() - startDate.getTime()) / 1000) / 60);

//render current temp basal
display.oled.setCursor(0,0);
var tempRate = Math.round(temp.rate*10)/10;
display.oled.writeString(font, 1, "TB: "+temp.duration+'m '+tempRate+'U/h '+'('+minutes+'m ago)', 1);
}

try {
//calculate timeago for status
var stats = fs.statSync("/root/myopenaps/monitor/last_temp_basal.json");
startDate = new Date(stats.mtime);
endDate = new Date();
minutes = Math.round((endDate.getTime() - startDate.getTime()) / 1000 / 60);

//render current temp basal
display.oled.setCursor(0, 0);
var tempRate = Math.round(temp.rate * 10) / 10;
display.oled.writeString(
font,
1,
"TB: " +
temp.duration +
"m " +
tempRate +
"U/h " +
"(" +
minutes +
"m ago)",
1
);

try {
var iob = JSON.parse(fs.readFileSync("/root/myopenaps/monitor/iob.json"));
} catch (e) {
} catch (e) {
return console.error("Could not parse iob.json: ", e);
}
}

try {
try {
var cob = JSON.parse(fs.readFileSync("/root/myopenaps/monitor/meal.json"));
} catch (e) {
} catch (e) {
return console.error("Could not parse meal.json: ", e);
}
//parse and render COB/IOB
display.oled.setCursor(0, 8);
display.oled.writeString(
font,
1,
"COB: " + cob.mealCOB + "g IOB: " + iob[0].iob + "U",
1,
true
);
}
//parse and render COB/IOB
display.oled.setCursor(0,8);
display.oled.writeString(font, 1, "COB: "+cob.mealCOB+"g IOB: "+iob[0].iob+'U', 1, true);