forked from FOSS/BangleApps
Merge pull request #1979 from Stiralbios/master
[TerminalClock] Use ClockFace module and add the ability to personalize the line ordermaster
commit
85be2caece
|
@ -4,3 +4,4 @@
|
|||
0.04: Fix settings bug
|
||||
0.05: Add altitude display (only Bangle.js 2)
|
||||
0.06: Add power related settings to control the HR and pressure(altitude) sensor from the watchface
|
||||
0.07: Use ClockFace module and rework the settings to be able to personnalize the order of the lines
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
var locale = require("locale");
|
||||
var fontColor = g.theme.dark ? "#0f0" : "#000";
|
||||
const locale = require("locale");
|
||||
var heartRate = 0;
|
||||
var altitude = -9001;
|
||||
|
||||
const fontColor = g.theme.dark ? "#0f0" : "#000";
|
||||
// handling the differents versions of the Banglejs smartwatch screen sizes
|
||||
if (process.env.HWVERSION == 1){
|
||||
var paddingY = 3;
|
||||
|
@ -18,32 +18,82 @@ if (process.env.HWVERSION == 1){
|
|||
var font6x8DefaultTextSize = 2;
|
||||
}
|
||||
|
||||
function setFontSize(pos){
|
||||
// initialising the clockface
|
||||
const ClockFace = require("ClockFace");
|
||||
const clock = new ClockFace({
|
||||
precision: 60,
|
||||
settingsFile: "terminalclock.json",
|
||||
|
||||
init: function () {
|
||||
// check settings and set default if needed
|
||||
this.showHRM = false;
|
||||
this.showAltitude = false;
|
||||
this.lock_precision = this.precision;
|
||||
this.unlock_precision = 1;
|
||||
if (this.HRMinConfidence === undefined) this.HRMinConfidence = 50;
|
||||
if (this.PowerOnInterval === undefined) this.PowerOnInterval = 15;
|
||||
if (this.powerSaving===undefined) this.powerSaving = true;
|
||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(k => {
|
||||
if (this[k]===undefined){
|
||||
if(k == "L2") this[k] = "Date";
|
||||
else if(k == "L3") {
|
||||
this[k] = "HR";
|
||||
this.showHRM = true;
|
||||
}else if(k == "L4") this[k] = "Motion";
|
||||
else if(k == "L5") this[k] = "Steps";
|
||||
else if(k == "L6") this[k] = ">";
|
||||
else this[k] = "Empty";
|
||||
}
|
||||
else if (this[k]==="HR") this.showHRM = true;
|
||||
else if (this[k]==="Alt") this.showAltitude = true && process.env.HWVERSION == 2;
|
||||
});
|
||||
|
||||
// set the lock and unlock actions
|
||||
Bangle.on("lock", on => {
|
||||
if (on) lock();
|
||||
else unlock();
|
||||
});
|
||||
|
||||
// set the services (HRM, pressure sensor, etc....)
|
||||
if(!this.powerSaving){
|
||||
turnOnServices();
|
||||
} else{
|
||||
setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min
|
||||
}
|
||||
// start the clock unlocked
|
||||
unlock();
|
||||
},
|
||||
|
||||
draw: function (date) {
|
||||
var curPos = 1;
|
||||
g.setFontAlign(-1, -1);
|
||||
g.setColor(fontColor);
|
||||
drawTime(date, curPos);
|
||||
curPos++;
|
||||
|
||||
["L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9"].forEach(line => {
|
||||
if (this[line]==='Date') drawDate(date, curPos);
|
||||
else if (this[line]==='HR') drawHRM(curPos);
|
||||
else if (this[line]==='Motion') drawMotion(curPos);
|
||||
else if (this[line]==='Alt') drawAltitude(curPos);
|
||||
else if (this[line]==='Steps') drawStepCount(curPos);
|
||||
else if (this[line]==='>') drawInput(curPos);
|
||||
curPos++;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/* ----------------------------
|
||||
Draw related of specific lines
|
||||
-------------------------------- */
|
||||
|
||||
function drawLine(line, pos){
|
||||
if(pos == 1)
|
||||
g.setFont("6x8", font6x8FirstTextSize);
|
||||
else
|
||||
g.setFont("6x8", font6x8DefaultTextSize);
|
||||
}
|
||||
|
||||
function clearField(pos){
|
||||
var yStartPos = Bangle.appRect.y +
|
||||
paddingY * (pos - 1) +
|
||||
font6x8At4Size * Math.min(1, pos-1) +
|
||||
font6x8At2Size * Math.max(0, pos-2);
|
||||
var yEndPos = Bangle.appRect.y +
|
||||
paddingY * (pos - 1) +
|
||||
font6x8At4Size * Math.min(1, pos) +
|
||||
font6x8At2Size * Math.max(0, pos-1);
|
||||
g.clearRect(Bangle.appRect.x, yStartPos, Bangle.appRect.x2, yEndPos);
|
||||
}
|
||||
|
||||
function clearWatchIfNeeded(now){
|
||||
if(now.getMinutes() % 10 == 0)
|
||||
g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y2);
|
||||
}
|
||||
|
||||
function drawLine(line, pos){
|
||||
setFontSize(pos);
|
||||
var yPos = Bangle.appRect.y +
|
||||
paddingY * (pos - 1) +
|
||||
font6x8At4Size * Math.min(1, pos-1) +
|
||||
|
@ -66,7 +116,6 @@ function drawDate(now, pos){
|
|||
}
|
||||
|
||||
function drawInput(pos){
|
||||
clearField(pos);
|
||||
drawLine(">", pos);
|
||||
}
|
||||
|
||||
|
@ -77,7 +126,6 @@ function drawStepCount(pos){
|
|||
}
|
||||
|
||||
function drawHRM(pos){
|
||||
clearField(pos);
|
||||
if(heartRate != 0)
|
||||
drawLine(">HR: " + parseInt(heartRate), pos);
|
||||
else
|
||||
|
@ -85,60 +133,30 @@ function drawHRM(pos){
|
|||
}
|
||||
|
||||
function drawAltitude(pos){
|
||||
clearField(pos);
|
||||
if(altitude > 0)
|
||||
drawLine(">Alt: " + altitude.toFixed(1) + "m", pos);
|
||||
else
|
||||
drawLine(">Alt: unknown", pos);
|
||||
}
|
||||
|
||||
function drawActivity(pos){
|
||||
clearField(pos);
|
||||
function drawMotion(pos){
|
||||
var health = Bangle.getHealthStatus('last');
|
||||
var steps_formated = ">Motion: " + parseInt(health.movement);
|
||||
drawLine(steps_formated, pos);
|
||||
}
|
||||
|
||||
function draw(){
|
||||
var curPos = 1;
|
||||
g.reset();
|
||||
g.setFontAlign(-1, -1);
|
||||
g.setColor(fontColor);
|
||||
var now = new Date();
|
||||
clearWatchIfNeeded(now); // mostly to not have issues when changing days
|
||||
drawTime(now, curPos);
|
||||
curPos++;
|
||||
if(settings.showDate){
|
||||
drawDate(now, curPos);
|
||||
curPos++;
|
||||
}
|
||||
if(settings.showAltitude){
|
||||
drawAltitude(curPos);
|
||||
curPos++;
|
||||
}
|
||||
if(settings.showHRM){
|
||||
drawHRM(curPos);
|
||||
curPos++;
|
||||
}
|
||||
if(settings.showActivity){
|
||||
drawActivity(curPos);
|
||||
curPos++;
|
||||
}
|
||||
if(settings.showStepCount){
|
||||
drawStepCount(curPos);
|
||||
curPos++;
|
||||
}
|
||||
drawInput(curPos);
|
||||
}
|
||||
/* -----------------------------------------------
|
||||
Services functions (HRM, pressure, etc...)
|
||||
-------------------------------------------------- */
|
||||
|
||||
function turnOnServices(){
|
||||
if(settings.showHRM){
|
||||
if(clock.showHRM){
|
||||
Bangle.setHRMPower(true, "terminalclock");
|
||||
}
|
||||
if(settings.showAltitude && process.env.HWVERSION != 1){
|
||||
if(clock.showAltitude){
|
||||
Bangle.setBarometerPower(true, "terminalclock");
|
||||
}
|
||||
if(settings.powerSaving){
|
||||
if(clock.powerSaving){
|
||||
setTimeout(function () {
|
||||
turnOffServices();
|
||||
}, 45000);
|
||||
|
@ -146,33 +164,20 @@ function turnOnServices(){
|
|||
}
|
||||
|
||||
function turnOffServices(){
|
||||
if(settings.showHRM){
|
||||
if(clock.showHRM){
|
||||
Bangle.setHRMPower(false, "terminalclock");
|
||||
}
|
||||
if(settings.showAltitude && process.env.HWVERSION != 1){
|
||||
if(clock.showAltitude){
|
||||
Bangle.setBarometerPower(false, "terminalclock");
|
||||
}
|
||||
}
|
||||
|
||||
var unlockDrawIntervalID = -1;
|
||||
Bangle.on('lock', function(on){
|
||||
if(!on){ // unclock
|
||||
if(settings.powerSaving){
|
||||
turnOnServices();
|
||||
}
|
||||
unlockDrawIntervalID = setInterval(draw, 1000); // every second
|
||||
}
|
||||
if(on && unlockDrawIntervalID != -1){ // lock
|
||||
clearInterval(unlockDrawIntervalID);
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.on('HRM',function(hrmInfo) {
|
||||
if(hrmInfo.confidence >= settings.HRMinConfidence)
|
||||
if(hrmInfo.confidence >= clock.HRMinConfidence)
|
||||
heartRate = hrmInfo.bpm;
|
||||
});
|
||||
|
||||
var MEDIANLENGTH = 20; // technical
|
||||
const MEDIANLENGTH = 20; // technical
|
||||
var avr = [], median; // technical
|
||||
Bangle.on('pressure', function(e) {
|
||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||
|
@ -184,32 +189,22 @@ Bangle.on('pressure', function(e) {
|
|||
}
|
||||
});
|
||||
|
||||
/* -------------------------------------------------
|
||||
Clock related functions but not in the ClockFace module
|
||||
---------------------------------------------------- */
|
||||
|
||||
// Clear the screen once, at startup
|
||||
g.clear();
|
||||
// load the settings
|
||||
var settings = Object.assign({
|
||||
// default values
|
||||
HRMinConfidence: 50,
|
||||
showDate: true,
|
||||
showHRM: true,
|
||||
showActivity: true,
|
||||
showStepCount: true,
|
||||
showAltitude: process.env.HWVERSION != 1 ? true : false,
|
||||
powerSaving: true,
|
||||
PowerOnInterval: 15,
|
||||
}, require('Storage').readJSON("terminalclock.json", true) || {});
|
||||
|
||||
// turn the services before drawing anything
|
||||
function unlock(){
|
||||
if(clock.powerSaving){
|
||||
turnOnServices();
|
||||
if(settings.powerSaving){
|
||||
setInterval(turnOnServices, settings.PowerOnInterval*60000); // every PowerOnInterval min
|
||||
}
|
||||
// Show launcher when middle button pressed
|
||||
Bangle.setUI("clock");
|
||||
// Load and draw widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
// draw immediately at first
|
||||
draw();
|
||||
setInterval(draw, 10000); // every 10 seconds
|
||||
clock.precision = clock.unlock_precision;
|
||||
clock.tick();
|
||||
}
|
||||
|
||||
function lock(){
|
||||
clock.precision = clock.lock_precision;
|
||||
clock.tick();
|
||||
}
|
||||
|
||||
// starting the clock
|
||||
clock.start();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Terminal Clock",
|
||||
"shortName":"Terminal Clock",
|
||||
"description": "A terminal cli like clock displaying multiple sensor data",
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"icon": "app.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
|
|
|
@ -2,22 +2,57 @@
|
|||
var FILE = "terminalclock.json";
|
||||
// Load settings
|
||||
var settings = Object.assign({
|
||||
// ClockFace lib
|
||||
loadWidgets: true,
|
||||
// TerminalClock specific
|
||||
HRMinConfidence: 50,
|
||||
showDate: true,
|
||||
showAltitude: process.env.HWVERSION != 1 ? true : false,
|
||||
showHRM: true,
|
||||
showActivity: true,
|
||||
showStepCount: true,
|
||||
powerSaving: true,
|
||||
PowerOnInterval: 15,
|
||||
L2: 'Date',
|
||||
L3: 'HR',
|
||||
L4: 'Motion',
|
||||
L5: 'Steps',
|
||||
L6: '>',
|
||||
L7: 'Empty',
|
||||
L8: 'Empty',
|
||||
L9: 'Empty',
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
|
||||
// Show the menu
|
||||
var menu = {
|
||||
if(process.env.HWVERSION == 2) {
|
||||
var lineType = ['Date', 'HR', 'Motion', 'Alt', 'Steps', '>', 'Empty'];
|
||||
} else{
|
||||
var lineType = ['Date', 'HR', 'Motion', 'Steps', '>', 'Empty'];
|
||||
}
|
||||
function getLineChooser(lineID){
|
||||
return {
|
||||
value: lineType.indexOf(settings[lineID]),
|
||||
min: 0, max: lineType.length-1,
|
||||
format: v => lineType[v],
|
||||
onchange: v => {
|
||||
settings[lineID] = lineType[v];
|
||||
writeSettings();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var lineMenu = {
|
||||
'< Back': function() { E.showMenu(getMainMenu());},
|
||||
'Line 2': getLineChooser('L2'),
|
||||
'Line 3': getLineChooser('L3'),
|
||||
'Line 4': getLineChooser('L4'),
|
||||
'Line 5': getLineChooser('L5'),
|
||||
'Line 6': getLineChooser('L6'),
|
||||
'Line 7': getLineChooser('L7'),
|
||||
'Line 8': getLineChooser('L8'),
|
||||
'Line 9': getLineChooser('L9'),
|
||||
};
|
||||
|
||||
function getMainMenu(){
|
||||
var mainMenu = {
|
||||
"" : { "title" : "Terminal Clock" },
|
||||
"< Back" : () => back(),
|
||||
'HR confidence': {
|
||||
|
@ -28,68 +63,39 @@
|
|||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Show date': {
|
||||
value: settings.showDate,
|
||||
format: v => v?"Yes":"No",
|
||||
'Show widgets': {
|
||||
value: settings.loadWidgets,
|
||||
onchange: v => {
|
||||
settings.showDate = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Show Altitude': {
|
||||
value: settings.showAltitude,
|
||||
format: v => v?"Yes":"No",
|
||||
onchange: v => {
|
||||
settings.showAltitude = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Show HRM': {
|
||||
value: settings.showHRM,
|
||||
format: v => v?"Yes":"No",
|
||||
onchange: v => {
|
||||
settings.showHRM = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Show Activity': {
|
||||
value: settings.showActivity,
|
||||
format: v => v?"Yes":"No",
|
||||
onchange: v => {
|
||||
settings.showActivity = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Show Steps': {
|
||||
value: settings.showStepCount,
|
||||
format: v => v?"Yes":"No",
|
||||
onchange: v => {
|
||||
settings.showStepCount = v;
|
||||
settings.loadWidgets = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Power saving': {
|
||||
value: settings.powerSaving,
|
||||
format: v => v?"On":"Off",
|
||||
onchange: v => {
|
||||
settings.powerSaving = v;
|
||||
writeSettings();
|
||||
setTimeout(function() {
|
||||
E.showMenu(getMainMenu());
|
||||
},0);
|
||||
}
|
||||
},
|
||||
'Power on interval': {
|
||||
}
|
||||
};
|
||||
if(settings.powerSaving){
|
||||
mainMenu['Power on interval'] = {
|
||||
value: settings.PowerOnInterval,
|
||||
min: 3, max: 60,
|
||||
onchange: v => {
|
||||
settings.PowerOnInterval = v;
|
||||
writeSettings();
|
||||
},
|
||||
format: x => {
|
||||
return x + " min";
|
||||
format: x => x + "m"
|
||||
};
|
||||
}
|
||||
|
||||
mainMenu['Lines'] = function() { E.showMenu(lineMenu);};
|
||||
return mainMenu;
|
||||
}
|
||||
}
|
||||
if (process.env.HWVERSION == 1) {
|
||||
delete menu['Show Altitude']
|
||||
}
|
||||
E.showMenu(menu);
|
||||
|
||||
E.showMenu(getMainMenu());
|
||||
})
|
Loading…
Reference in New Issue