359 lines
13 KiB
JavaScript
359 lines
13 KiB
JavaScript
(function (back) {
|
|
|
|
var settingsJSON = "heatsuite.settings.json";
|
|
var studyTasksJSON = "heatsuite.tasks.json";
|
|
|
|
function log(msg) {
|
|
if (!settings.DEBUG) {
|
|
return;
|
|
} else {
|
|
console.log(msg);
|
|
}
|
|
}
|
|
|
|
function writeSettings(key, value) {
|
|
var s = require('Storage').readJSON(settingsJSON, true) || {};
|
|
s[key] = value;
|
|
require('Storage').writeJSON(settingsJSON, s);
|
|
settings = readSettings();
|
|
if (global.WIDGETS && WIDGETS["heatsuite"]) WIDGETS["heatsuite"].changed(); //redraw widget on settings update if open
|
|
}
|
|
|
|
function readSettings() {
|
|
var out = Object.assign(
|
|
require('Storage').readJSON("heatsuite.default.json", true) || {},
|
|
require('Storage').readJSON(settingsJSON, true) || {}
|
|
);
|
|
out.StudyTasks = require('Storage').readJSON(studyTasksJSON, true) || {};
|
|
return out;
|
|
}
|
|
var settings = readSettings();
|
|
|
|
/*---- PAIRING FUNCTIONS FOR DEVICES ----*/
|
|
function BPPair(id) {
|
|
var device;
|
|
E.showMessage(`Pairing /n ${id}`, "Bluetooth");
|
|
NRF.connect(id).then(function (d) {
|
|
device = d;
|
|
return new Promise(resolve => setTimeout(resolve, 2000));
|
|
}).then(function () {
|
|
log("connected");
|
|
if (device.getSecurityStatus().bonded) {
|
|
log("Already bonded");
|
|
return true;
|
|
} else {
|
|
log("Start bonding");
|
|
return device.startBonding();
|
|
}
|
|
}).then(function () {
|
|
device.device.on('gattserverdisconnected', function (reason) {
|
|
log("Disconnected ", reason);
|
|
});
|
|
return device.getPrimaryService("1810");
|
|
}).then(function (service) {
|
|
log(service);
|
|
return service.getCharacteristic("2A08");
|
|
}).then(function (characteristic) {
|
|
//set time on device during pairing
|
|
var date = new Date();
|
|
var b = new ArrayBuffer(7);
|
|
var v = new DataView(b);
|
|
v.setUint16(0, date.getFullYear(), true);
|
|
v.setUint8(2, date.getMonth() + 1);
|
|
v.setUint8(3, date.getDate());
|
|
v.setUint8(4, date.getHours());
|
|
v.setUint8(5, date.getMinutes());
|
|
v.setUint8(5, date.getSeconds());
|
|
var arr = [];
|
|
for (let i = 0; i < v.buffer.length; i++) {
|
|
arr[i] = v.buffer[i];
|
|
}
|
|
return characteristic.writeValue(arr);
|
|
}).then(function () {
|
|
writeSettings("bt_bloodPressure_id", id);
|
|
// Store the name for displaying later. Will connect by ID
|
|
if (device.name) {
|
|
writeSettings("bt_bloodPressure_name", device.name);
|
|
}
|
|
E.showAlert("Paired!").then(function () { E.showMenu(deviceSettings()) });
|
|
log("Device ID paired, time set, Done!");
|
|
return device.disconnect();
|
|
}).catch(function (e) {
|
|
log(e);
|
|
E.showAlert("error! " + e).then(function () { E.showMenu(deviceSettings()) });
|
|
});
|
|
}
|
|
function PairTcore(id) {
|
|
E.showMessage(`Pairing /n ${id}`, "Bluetooth");
|
|
var gatt;
|
|
NRF.connect(id).then(function (g) {
|
|
gatt = g;
|
|
console.log("connected!!!");
|
|
// return gatt.startBonding();
|
|
//}).then(function() {
|
|
console.log("bonded", gatt.getSecurityStatus());
|
|
writeSettings("bt_coreTemperature_id", id);
|
|
E.showAlert("Paired!").then(function () { E.showMenu(deviceSettings()) });
|
|
log("Device ID paired, Done!");
|
|
gatt.disconnect();
|
|
}).catch(function (e) {
|
|
log("ERROR: " + e);
|
|
E.showAlert("error! " + e).then(function () { E.showMenu(deviceSettings()) });
|
|
});
|
|
}
|
|
|
|
function deviceSettings() {
|
|
var menu = { '< Back': function () { E.showMenu(mainMenuSettings()); } };
|
|
menu[''] = { 'title': 'Devices' };
|
|
settings.StudyTasks.forEach(task => {
|
|
if (task.btPair === undefined || !task.btPair) return;
|
|
let key = task.id; // Adjust based on how you identify tasks
|
|
let id = "bt_" + key + "_id";
|
|
if (settings[id] !== undefined) {
|
|
menu["Clear " + key] = function () {
|
|
E.showPrompt("Clear " + key + " device?").then((r) => {
|
|
if (r) {
|
|
writeSettings("bt_" + key + "_id", undefined);
|
|
writeSettings("bt_" + key + "_name", undefined);
|
|
}
|
|
E.showMenu(mainMenuSettings());
|
|
});
|
|
};
|
|
} else {
|
|
menu["Pair " + key] = () => createMenuFromScan(key, task.btInfo.service);
|
|
}
|
|
});
|
|
return menu;
|
|
}
|
|
|
|
function recordMenu(){
|
|
var updateRecorder = function(name,v){
|
|
var r = settings.record;
|
|
r = r.filter(item => item !== name);
|
|
if(v){
|
|
r.push(name);
|
|
}
|
|
writeSettings("record",r);
|
|
}
|
|
var menu = { '< Back': function () { E.showMenu(mainMenuSettings()); } };
|
|
menu[''] = { 'title': 'Recorder' };
|
|
var recorderOptions = {
|
|
'hrm' : 'Optical HR',
|
|
'steps' : "Steps",
|
|
'bat' : 'Battery',
|
|
'movement': 'Movement',
|
|
'acc':'Accelerometry',
|
|
'baro':'Temp/Pressure',
|
|
'bthrm': 'BT HRM',
|
|
'CORESensor':'CORE Sensor'
|
|
}
|
|
for (let key in recorderOptions) {
|
|
let name = recorderOptions[key];
|
|
menu[name] = {
|
|
value: settings.record.includes(key),
|
|
onchange: v => {updateRecorder(key,v);}
|
|
};
|
|
}
|
|
menu['High Acc'] = {
|
|
value: settings.highAcc || false,
|
|
onchange: v => {
|
|
settings.highAcc = v;
|
|
writeSettings("highAcc", v);
|
|
}
|
|
};
|
|
return menu;
|
|
}
|
|
|
|
function mainMenuSettings() {
|
|
var menu = {
|
|
'': { 'title': 'Main' },
|
|
'< Back': back
|
|
};
|
|
|
|
menu['Recorders'] = function () {E.showMenu(recordMenu()) };
|
|
menu['Devices'] = function () { E.showMenu(deviceSettings()) };
|
|
menu['GPS'] = function () { E.showMenu(gpsSettings()) };
|
|
menu['Language'] = function () { E.showMenu(languageMenu()) };
|
|
menu['Swipe Launch'] = {
|
|
value: settings.swipeOpen || false,
|
|
onchange: v => {
|
|
settings.swipeOpen = v;
|
|
writeSettings("swipeOpen", v);
|
|
}
|
|
};
|
|
menu['Survey Random'] = {
|
|
value: settings.surveyRandomize || false,
|
|
onchange: v => {
|
|
settings.GPS = v;
|
|
writeSettings("surveyRandomize", v);
|
|
}
|
|
};
|
|
menu['HRM Interval'] = {
|
|
value: settings.HRMInterval || 0,
|
|
min: 0, max: 60,
|
|
onchange: v => {
|
|
settings.HRMInterval = v;
|
|
writeSettings("HRMInterval", v);
|
|
}
|
|
};
|
|
menu['Restart BLE'] = function () {
|
|
E.showPrompt("Restart Bluetooth?").then((r) => {
|
|
if (r) {
|
|
NRF.disconnect()
|
|
NRF.restart();
|
|
}
|
|
E.showMenu(mainMenuSettings());
|
|
});
|
|
};
|
|
menu['Clear Cache'] = function () {
|
|
E.showPrompt("Clear Cache?").then((r) => {
|
|
if (r) {
|
|
require('Storage').writeJSON("heatsuite.cache.json", {});
|
|
}
|
|
E.showMenu(mainMenuSettings());
|
|
});
|
|
}
|
|
menu['Clear Study ID'] = function () {
|
|
E.showPrompt("Clear study ID (includes ignored)?").then((r) => {
|
|
if (r) {
|
|
writeSettings("studyID", undefined);
|
|
writeSettings("studyIDIgnore", []);
|
|
}
|
|
E.showMenu(mainMenuSettings());
|
|
});
|
|
}
|
|
menu['Notifications'] = {
|
|
value: settings.notifications || false,
|
|
onchange: v => {
|
|
settings.notifications = v;
|
|
writeSettings("notifications", v);
|
|
}
|
|
};
|
|
menu['Debug'] = function () { E.showMenu(debugMenu()) };
|
|
return menu;
|
|
}
|
|
function debugMenu(){
|
|
var menu = {
|
|
'': { 'title': 'Debug' },
|
|
'< Back': function () { E.showMenu(mainMenuSettings()); }
|
|
};
|
|
menu['Console'] = {
|
|
value: settings.DEBUG || false,
|
|
onchange: v => {
|
|
settings.DEBUG = v;
|
|
writeSettings("DEBUG", v);
|
|
}
|
|
};
|
|
menu['Log (file)'] = {
|
|
value: settings.SAVE_DEBUG || false,
|
|
onchange: v => {
|
|
settings.SAVE_DEBUG = v;
|
|
writeSettings("SAVE_DEBUG", v);
|
|
}
|
|
};
|
|
return menu;
|
|
}
|
|
function gpsSettings() {
|
|
var menu = {
|
|
'': { 'title': 'GPS' },
|
|
'< Back': function () { E.showMenu(mainMenuSettings()); }
|
|
};
|
|
menu['GPS'] = {
|
|
value: settings.GPS || false,
|
|
onchange: v => {
|
|
settings.GPS = v;
|
|
writeSettings("GPS", v);
|
|
}
|
|
};
|
|
menu['Scan Time (min)'] = {
|
|
value: settings.GPSScanTime || 1,
|
|
min: 0, max: 60,
|
|
onchange: v => {
|
|
settings.GPSScanTime = v;
|
|
writeSettings("GPSScanTime", v);
|
|
}
|
|
};
|
|
menu['Interval (min)'] = {
|
|
value: settings.GPSInterval || 10,
|
|
min: 0, max: 180,
|
|
onchange: v => {
|
|
settings.GPSinterval = v;
|
|
writeSettings("GPSInterval", v);
|
|
}
|
|
};
|
|
menu['Adaptive (min)'] = {
|
|
value: settings.GPSAdaptiveTime || 2,
|
|
min: 0, max: 60,
|
|
onchange: v => {
|
|
settings.GPSAdaptiveTime = v;
|
|
writeSettings("GPSAdaptiveTime", v);
|
|
}
|
|
};
|
|
return menu;
|
|
}
|
|
|
|
function languageMenu() {
|
|
var menu = { '< Back': function () { E.showMenu(mainMenuSettings()); } };
|
|
menu[''] = { 'title': 'Language' };
|
|
var surveySettings = require('Storage').readJSON("heatsuite.survey.json", true) || {};
|
|
|
|
Object.keys(surveySettings.supported).forEach(key => {
|
|
//var id = surveySettings.supported[key];
|
|
menu[key] = function () {
|
|
E.showPrompt("Set " + key + "?").then((r) => {
|
|
if (r) {
|
|
writeSettings('lang', key);
|
|
}
|
|
E.showMenu(mainMenuSettings());
|
|
});
|
|
};
|
|
});
|
|
return menu;
|
|
}
|
|
|
|
function createMenuFromScan(type, service) {
|
|
E.showMenu();
|
|
E.showMessage("Scanning for 4 seconds");
|
|
var submenu_scan = {
|
|
'< Back': function () { E.showMenu(deviceSettings()); }
|
|
};
|
|
NRF.findDevices(function (devices) {
|
|
submenu_scan[''] = { title: `Scan (${devices.length} found)` };
|
|
if (devices.length === 0) {
|
|
E.showAlert("No " + type + " devices found")
|
|
.then(() => E.showMenu(deviceSettings()));
|
|
return;
|
|
} else {
|
|
devices.forEach((d) => {
|
|
print("Found device", d);
|
|
var shown = (d.name || d.id.substr(0, 17));
|
|
submenu_scan[shown] = function () {
|
|
E.showPrompt("Set " + shown + "?").then((r) => {
|
|
if (r) {
|
|
switch (type) {
|
|
case "bloodPressure":
|
|
BPPair(d.id);
|
|
break;
|
|
case "coreTemperature":
|
|
PairTcore(d.id);
|
|
break;
|
|
case "bthrm":
|
|
|
|
break;
|
|
default:
|
|
E.showMenu(deviceSettings());
|
|
break;
|
|
}
|
|
} else {
|
|
E.showMenu(deviceSettings());
|
|
}
|
|
});
|
|
};
|
|
});
|
|
}
|
|
E.showMenu(submenu_scan);
|
|
}, { timeout: 4000, active: true, filters: [{ services: [service] }] });
|
|
}
|
|
|
|
E.showMenu(mainMenuSettings());
|
|
}) |