{ const locale = require("locale"); let heartRate = 0; let altitude = -9001; const fontColor = g.theme.dark ? "#0f0" : "#000"; // handling the differents versions of the Banglejs smartwatch screen sizes // default BJS2 let paddingY = 2; let font6x8At4Size = 32; let font6x8At2Size = 18; let font6x8FirstTextSize = 4; let font6x8DefaultTextSize = 2; if (process.env.HWVERSION == 1){ paddingY = 3; font6x8At4Size = 48; font6x8At2Size = 27; font6x8FirstTextSize = 6; font6x8DefaultTextSize = 3; } // 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.powerSave===undefined) this.powerSave = this.powerSaving; // migrate old setting if (this.powerSave===undefined) this.powerSave = 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 services (HRM, pressure sensor, etc....) if(!this.powerSave){ turnOnServices(); } else{ this.turnOnInterval = setInterval(turnOnServices, this.PowerOnInterval*60000); // every PowerOnInterval min } // start the clock unlocked unlock(); }, draw: function (date) { let 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++; }); }, remove: function() { if (this.turnOnInterval){ clearInterval(this.turnOnInterval); delete this.turnOnInterval; } if (this.turnOffServiceTimeout){ clearTimeout(this.turnOffServiceTimeout) delete this.turnOffServiceTimeout } turnOffServices(); if (this.onLock) Bangle.removeListener('lock', this.onLock); if (this.onHRM) Bangle.removeListener('HRM', this.onHRM); if (this.onPressure) Bangle.removeListener('pressure', this.onPressure); } }); /* ---------------------------- Draw related of specific lines -------------------------------- */ let drawLine = function(line, pos){ if(pos == 1) g.setFont("6x8", font6x8FirstTextSize); else g.setFont("6x8", font6x8DefaultTextSize); let yPos = Bangle.appRect.y + paddingY * (pos - 1) + font6x8At4Size * Math.min(1, pos-1) + font6x8At2Size * Math.max(0, pos-2); g.drawString(line, 5, yPos, true); }; let drawTime = function(now, pos){ let h = now.getHours(); let m = now.getMinutes(); let time = ">" + (""+h).substr(-2) + ":" + ("0"+m).substr(-2); drawLine(time, pos); }; let drawDate = function(now, pos){ let dow = locale.dow(now, 1); let date = locale.date(now, 1).substr(0,6) + locale.date(now, 1).substr(-2); let locale_date = ">" + dow + " " + date; drawLine(locale_date, pos); }; let drawInput = function(pos){ drawLine(">", pos); }; let drawStepCount = function(pos){ let health = Bangle.getHealthStatus("day"); let steps_formated = ">Steps: " + health.steps; drawLine(steps_formated, pos); }; let drawHRM = function(pos){ if(heartRate != 0) drawLine(">HR: " + parseInt(heartRate), pos); else drawLine( ">HR: " + parseInt(Math.round(Bangle.getHealthStatus().bpm||Bangle.getHealthStatus("last").bpm)), pos); }; let drawAltitude = function(pos){ if(altitude > 0) drawLine(">Alt: " + altitude.toFixed(1) + "m", pos); else drawLine(">Alt: unknown", pos); }; let drawMotion = function(pos){ let health = Bangle.getHealthStatus('last'); let steps_formated = ">Motion: " + parseInt(health.movement); drawLine(steps_formated, pos); }; /* ----------------------------------------------- Services functions (HRM, pressure, etc...) -------------------------------------------------- */ let turnOnServices = function(){ if(clock.showHRM){ Bangle.setHRMPower(true, "terminalclock"); } if(clock.showAltitude){ Bangle.setBarometerPower(true, "terminalclock"); } if(clock.powerSave){ if(clock.turnOffServiceTimeout) clearTimeout(clock.turnOffServiceTimeout); clock.turnOffServiceTimeout = setTimeout(function () { turnOffServices(); }, 45000); } }; let turnOffServices = function(){ if(clock.showHRM){ Bangle.setHRMPower(false, "terminalclock"); } if(clock.showAltitude){ Bangle.setBarometerPower(false, "terminalclock"); } }; // set the lock and unlock actions clock.onLock = lock_event => { if (lock_event) lock(); else unlock(); }; Bangle.on("lock", clock.onLock); clock.onHRM = hrmInfo => { if(hrmInfo.confidence >= clock.HRMinConfidence) heartRate = hrmInfo.bpm; }; Bangle.on('HRM', clock.onHRM); const MEDIANLENGTH = 20; // technical let avr = [], median; // technical clock.onPressure = pressureInfo => { while (avr.length>MEDIANLENGTH) avr.pop(); avr.unshift(pressureInfo.altitude); median = avr.slice().sort(); if (median.length>10) { let mid = median.length>>1; altitude = E.sum(median.slice(mid-4,mid+5)) / 9; } else altitude = pressureInfo.altitude; }; Bangle.on('pressure', clock.onPressure); /* ------------------------------------------------- Clock related functions but not in the ClockFace module ---------------------------------------------------- */ let unlock = function(){ if(clock.powerSave){ turnOnServices(); } clock.precision = clock.unlock_precision; clock.tick(); }; let lock = function(){ clock.precision = clock.lock_precision; clock.tick(); }; // starting the clock clock.start(); }