import document from "document"; import clock from "clock"; import * as messaging from "messaging"; import * as fs from "fs"; import { HeartRateSensor } from "heart-rate"; import { today } from "user-activity"; import { goals } from "user-activity"; import { vibration } from "haptics"; import { display } from "display"; import { preferences } from "user-settings"; import { me as device } from "device"; if (!device.screen) device.screen = { width: 348, height: 250 }; const placeholder = 'ยทยทยท'; const colorSchemes = { blues: ["#343375", "#6795b1"], aurora: ["#320c72", "#24c2bf"], roast: ["#ba8867", "#3c2710"], blush: ["#d09593", "#c71d6f"], ponyhair: ["#e9438b", "#9acccd"], lime: ["#dde170", "#06a33e"], dawn: ["#3b93c5", "#9f59a9"], peach: ["#fcbd95", "#f795a4"], violet: ["#9d25eb", "#4e6cc3"], } const weekdays = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]; let progress = 0; let progressXPos = 1; let progressEl = document.getElementById('progress'); let timeEl = document.getElementById('time'); let dateEl = document.getElementById('date'); let hrEl = document.getElementById('hr'); let heartEl = document.getElementById('heartbeat'); let textElements = document.getElementsByClassName('text'); let textOffset = 20; let hrOffset = 42; let hrm = new HeartRateSensor; let hrTimer; var colorDef = [ colorSchemes['violet'][0], colorSchemes['violet'][1] ]; var storedColorDef; var fileSuccess = true; console.log('reading color def'); try { storedColorDef = fs.readFileSync("colordef.txt", "cbor"); } catch(err) { fileSuccess = false; console.log('color def not found'); } if (fileSuccess) { colorDef = storedColorDef; } hrEl.text = placeholder; function zeroPad(i) { if (i < 10) { i = "0" + i; } return i; } function updateClock() { let currDate = new Date(); let hours = currDate.getHours(); let displayHours = hours; if (preferences.clockDisplay === '12h') { displayHours = displayHours % 12; displayHours = displayHours ? displayHours : 12; } let minutes = zeroPad(currDate.getMinutes()); let day = currDate.getDate(); //let month = currDate.getMonth()+1; let weekday = weekdays[currDate.getDay()]; let timeString = `${displayHours}:${minutes}`; timeEl.text = timeString; let dateString = `${weekday} ${day}`; dateEl.text = dateString; updateProgress(); progressEl.width = progressXPos; if (progress <= 0.5) { for(let i=0; i < textElements.length; i++) { textElements[i].x = progressXPos + textOffset; textElements[i].textAnchor = 'start'; } heartEl.x = progressXPos + textOffset - 8; hrEl.x = progressXPos + textOffset + hrOffset; hrEl.textAnchor = 'start'; } else { for(let i=0; i < textElements.length; i++) { textElements[i].x = progressXPos - textOffset; textElements[i].textAnchor = 'end'; } heartEl.x = progressXPos - textOffset - 38; hrEl.x = progressXPos - textOffset - hrOffset + 4; hrEl.textAnchor = 'end'; } } function updateProgress() { let steps = (today.adjusted.steps || null); if (steps !== null) { let stepGoal = (goals.steps || 0); progress = Math.min(steps/stepGoal, 1); progressXPos = Math.max(device.screen.width*progress, 10); } else { progress = 1; progressXPos = 10; } } function updateColor() { progressEl.gradient.colors.c1 = colorDef[0]; progressEl.gradient.colors.c2 = colorDef[1]; } hrm.onreading = () => { if (display.on) { let heartRate = (hrm.heartRate || placeholder); hrEl.text = heartRate; } clearTimeout(hrTimer); hrTimer = setTimeout(() => { hrEl.text = placeholder; }, 5000); hrm.stop(); } clock.granularity = "minutes"; clock.ontick = () => updateClock(); updateColor(); setInterval(() => { hrm.start(); }, 2000); messaging.peerSocket.onmessage = e => { console.log("Message received -> "+e.data.key+": "+e.data.newValue); display.poke(); vibration.start("bump"); switch (e.data.key) { case 'progresscolor': colorDef[0] = colorSchemes[e.data.newValue][0]; colorDef[1] = colorSchemes[e.data.newValue][1]; break; }; updateColor(); updateClock(); fs.writeFileSync("colordef.txt", colorDef, "cbor"); } messaging.peerSocket.onopen = () => { console.log("Clockface opened socket"); }; messaging.peerSocket.close = () => { console.log("Clockface closed socket"); }; messaging.peerSocket.onerror = (err) => { console.log("Clockface socket error: " + err.code + " - " + err.message); } function addcommas(nStr) { if (nStr < 1000) { return nStr; } nStr += ''; let x = nStr.split('.'); let x1 = x[0]; let x2 = x.length > 1 ? '.' + x[1] : ''; let rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); } return x1 + x2; } function getActivityNumber(activity) { let values = {raw: 0, display: 0}; switch (activity) { case 'steps': values.raw = (today.adjusted.steps || 0); values.display = addcommas(values.raw); break; case 'cal': values.raw = (today.adjusted.calories || 0); values.display = addcommas(values.raw); break; case 'dist': values.raw = (today.adjusted.distance || 0); values.display = (Math.round(values.raw/10)/100 || 0); break; case 'elev': values.raw = values.display = (today.adjusted.elevationGain || 0); break; case 'actmin': values.raw = (today.adjusted.activeMinutes || 0); values.display = addcommas(values.raw); break; }; return values; } function getActivityText(activity) { let label = placeholder; switch (activity) { case 'hr': label = hrLabel; break; case 'steps': case 'cal': case 'actmin': case 'dist': case 'elev': label = getActivityNumber(activity).display; break; default: break; }; return label; } let touchArea = document.getElementById('touchArea'); let overlay = document.getElementById('overlay'); let healthTextInstances = document.getElementsByClassName('healthTextInstance'); let timeElementsNum = timeElements.length; let hasOverlay = false; let overlayTimer; touchArea.onclick = (e) => { if (hasOverlay == false) { vibration.start("bump"); addOverlay(); } else { removeOverlay(); } } function updateOverlay() { document.getElementById('stepsText').getElementById('healthTextLabel').text = getActivityText('steps'); document.getElementById('calText').getElementById('healthTextLabel').text = getActivityText('cal'); document.getElementById('distText').getElementById('healthTextLabel').text = getActivityText('dist'); document.getElementById('elevText').getElementById('healthTextLabel').text = getActivityText('elev'); document.getElementById('actminText').getElementById('healthTextLabel').text = getActivityText('actmin'); } function addOverlay() { updateOverlay(); overlay.style.display = 'inline'; hasOverlay = true; overlayTimer = setTimeout(() => { removeOverlay(); },6000); document.getElementById('overlayShadeInstance').animate('enable'); for(let i in healthTextInstances) { setTimeout(() => { healthTextInstances[i].animate('enable'); }, 200+i*100); } } function removeOverlay() { clearTimeout(overlayTimer); document.getElementById('overlayShadeInstance').animate('disable'); for(var i = 0; i < healthTextInstances.length; i++) { healthTextInstances[i].animate('disable'); } setTimeout(() => { overlay.style.display = 'none'; }, 100); hasOverlay = false; }