{ // must be inside our own scope here so that when we are unloaded everything disappears // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global const STATE_IDLE = 0; const STATE_MENU_OPEN = 3; let apiKey = require("Storage").readJSON("apikey.json", null); if (!apiKey) { require("Storage").writeJSON("apikey.json", "NEEDTOSET"); } let watchState = STATE_IDLE; let stopWatch = require("Storage").readJSON("mystopwatch.json", true) || {start1: null, elapsed1: null, start2: null, elapsed2: null}; let saveStopWatch = function() { require("Storage").writeJSON("mystopwatch.json", stopWatch); } let stopWatchTimer = null; let myMessage = ""; let temperature = ""; let drawTimer = null; let menu = require("Storage").readJSON("menu.json", true); let subMenu = null; let menuCommand = ""; let drawStopWatches = function () { if (watchState != STATE_IDLE) return; var w = g.getWidth(); var x = w / 2; var y = g.getHeight() / 2; if (stopWatch.start1 || stopWatch.elapsed1) { let Tt1 = (stopWatch.elapsed1 || 0); if (stopWatch.start1) { Tt1 += Date.now() - stopWatch.start1; } let Ttxt1 = timeToText(Tt1); g.clearRect(0, y-60, w, y-34); g.setColor(g.theme.fg); g.setFontAlign(0, 0).setFont("Vector", 26).drawString("S1: " + Ttxt1, x, y-45); } if (stopWatch.start2 || stopWatch.elapsed2) { let Tt2 = (stopWatch.elapsed2 || 0); if (stopWatch.start2) { Tt2 += Date.now() - stopWatch.start2; } let Ttxt2 = timeToText(Tt2); g.clearRect(0, y+61, w, y+88); g.setColor(g.theme.fg); g.setFontAlign(0, 0).setFont("Vector", 26).drawString("S2: " + Ttxt2, x, y+76); } } let paintFace = function() { if (watchState != STATE_IDLE) return; var x = g.getWidth() / 2; var y = g.getHeight() / 2; g.reset().clearRect(Bangle.appRect); // clear whole background (w/o widgets) var date = new Date(); var timeStr = require("locale").time(date, 1); // Hour and minute g.setFontAlign(0, 0).setFont("Vector", 60).drawString(timeStr, x, y); // Used to be Anton, +20 var utc_sec = getTime(); var utc = utc_sec % 86400; var utcHour = Math.floor(utc / 3600); var utcMinute = Math.floor((utc % 3600) / 60); var utcStr = utcHour.toString().padStart(2, '0') + ":" + utcMinute.toString().padStart(2, '0'); g.setFontAlign(0, 0).setFont("Vector", 36).drawString(utcStr, x-25, y+43); var tz_offset = date.toString().indexOf("GMT"); var tz = date.toString().substring(tz_offset+3, tz_offset+6); g.setFontAlign(0, 0).setFont("Vector", 24).drawString(tz, x+60, y+43); // Show date and day of week const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; var dateStr = date.getDate() + " " + days[date.getDay()] + " " + temperature; // don't draw date string if stopwatch 2 is running if (!stopWatch.start2 && !stopWatch.elapsed2) { g.setFontAlign(0, 0).setFont("Vector", 26).drawString(dateStr, x, y+76); } //var wrapped = g.wrapString(myMessage, g.getWidth()-10).join("\n"); // don't draw message if stopwatch 1 is running if (!stopWatch.start1 && !stopWatch.elapsed1) { g.setFontAlign(0, 0).setFont("Vector", 26).drawString(myMessage, x, y-45); } drawStopWatches(); }; // Actually draw the watch face let draw = function() { if (Bangle.http){ Bangle.http("https://api.home.dns.t0.vc/bangle", {timeout:3000}).then(event => { let result = JSON.parse(event.resp); myMessage = result.context; temperature = result.temperature; if (watchState == STATE_IDLE) { if (paintFace) paintFace(); } }).catch((e)=>{ myMessage = "GET error"; if (paintFace) paintFace(); }); } // queue next draw if (drawTimer) clearTimeout(drawTimer); drawTimer = setTimeout(function() { drawTimer = undefined; draw(); }, 60000 - (Date.now() % 60000)); }; let timeToText = function(t) { let hrs = Math.floor(t/3600000); let mins = Math.floor(t/60000)%60; let secs = Math.floor(t/1000)%60; let tnth = Math.floor(t/100)%10; let text; if (hrs === 0) { text = ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2) + "." + tnth; } else { text = ("0"+hrs) + ":" + ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2); } return text; }; let handleSwipe = function(dir1, dir2) { var direction; if (dir1 == 1) { direction = "right"; } else if (dir1 == -1) { direction = "left"; } else if (dir2 == 1) { direction = "down"; } else if (dir2 == -1) { direction = "up"; } else { direction = "none"; } if (Bangle.http){ const headers = {"Authorization": "Bearer " + apiKey}; const options = {timeout:3000, method: "post", body: direction, headers: headers}; Bangle.http("https://api.home.dns.t0.vc/bangle", options).then(event => { myMessage = "Sent " + direction; if (paintFace) paintFace(); }).catch((e)=>{ myMessage = "POST error"; if (paintFace) paintFace(); }); } }; let drawMenu = function(menu) { const keys = Object.keys(menu); g.reset().clearRect(Bangle.appRect); g.drawLine(88, 0, 88, 175); // | g.drawLine(0, 88, 175, 88); // -- const wrap = function(text) { return g.wrapString(text, 80).join("\n"); }; g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[0]), 50, 50); // 0 g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[1]), 130, 50); // 1 g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[2]), 50, 130); // 2 g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[3]), 130, 130); // 3 }; let startSW1 = function() { console.log("Starting stopwatch 1..."); stopWatch.start1 = Date.now(); if (!stopWatch.elapsed1) { stopWatch.elapsed1 = 0; } saveStopWatch(); if (!stopWatchTimer) { drawStopWatches(); stopWatchTimer = setInterval(drawStopWatches, 100); } } let startSW2 = function() { console.log("Starting stopwatch 2..."); stopWatch.start2 = Date.now(); if (!stopWatch.elapsed2) { stopWatch.elapsed2 = 0; } saveStopWatch(); if (!stopWatchTimer) { drawStopWatches(); stopWatchTimer = setInterval(drawStopWatches, 100); } } let pauseSW1 = function() { if (!stopWatch.start1) return; stopWatch.elapsed1 += Date.now() - stopWatch.start1; stopWatch.start1 = null; saveStopWatch(); if (!stopWatch.start2) { if (stopWatchTimer) { clearInterval(stopWatchTimer); stopWatchTimer = null; } } }; let stopSW1 = function() { stopWatch.start1 = null; stopWatch.elapsed1 = null; saveStopWatch(); if (!stopWatch.start2) { if (stopWatchTimer) { clearInterval(stopWatchTimer); stopWatchTimer = null; } } }; let pauseSW2 = function() { if (!stopWatch.start2) return; stopWatch.elapsed2 += Date.now() - stopWatch.start2; stopWatch.start2 = null; saveStopWatch(); if (!stopWatch.start1) { if (stopWatchTimer) { clearInterval(stopWatchTimer); stopWatchTimer = null; } } }; let stopSW2 = function() { stopWatch.start2 = null; stopWatch.elapsed2 = null; saveStopWatch(); if (!stopWatch.start1) { if (stopWatchTimer) { clearInterval(stopWatchTimer); stopWatchTimer = null; } } }; let handleTouch = function(button, xy) { //console.log(button, xy); const touchX = xy.x; const touchY = xy.y; const pressed = xy.type == 0; // 0 1 // 2 3 let quad = -1; if (touchY < 110) { if (touchX < 110) { quad = 0; } else { quad = 1; } } else { if (touchX < 110) { quad = 2; } else { quad = 3; } } //console.log("quad:", quad); if (watchState == STATE_IDLE && pressed) { watchState = STATE_MENU_OPEN; subMenu = menu; menuCommand = ""; } const keys = Object.keys(subMenu); const key = keys[quad]; if (key == "stop watch") { subMenu = {}; const sw2key = stopWatch.start2 ? 'pause2' : 'start2'; subMenu[sw2key] = null; subMenu["stop2"] = null; const sw1key = stopWatch.start1 ? 'pause1' : 'start1'; subMenu[sw1key] = null; subMenu["stop1"] = null; } else { subMenu = subMenu[key]; } menuCommand += key + ","; //console.log("submenu:", subMenu); if (subMenu) { drawMenu(subMenu); } else { watchState = STATE_IDLE; console.log("menuCommand:", menuCommand); Bangle.drawWidgets(); Bangle.buzz(100, 0.2); if (menuCommand == "commands,util,pull menu,") { console.log("Pulling new menu..."); menu = null; require("Storage").writeJSON("menu.json", menu); } else if (menuCommand == "states,stop watch,start1,") { startSW1(); } else if (menuCommand == "states,stop watch,start2,") { startSW2(); } else if (menuCommand == "states,stop watch,pause1,") { pauseSW1(); } else if (menuCommand == "states,stop watch,pause2,") { pauseSW2(); } else if (menuCommand == "states,stop watch,stop1,") { stopSW1(); } else if (menuCommand == "states,stop watch,stop2,") { stopSW2(); } else { if (Bangle.http){ const headers = {"Authorization": "Bearer " + apiKey}; const options = {timeout:3000, method: "post", body: menuCommand, headers: headers}; Bangle.http("https://api.home.dns.t0.vc/menu", options).then(event => { myMessage = "ok"; if (paintFace) paintFace(); }).catch((e)=>{ myMessage = "POST error"; if (paintFace) paintFace(); }); } } myMessage = key; if (paintFace) paintFace(); } }; let handleTwist = function() { console.log("twisted"); if (watchState == STATE_MENU_OPEN) { watchState = STATE_IDLE; myMessage = "cancelled"; if (paintFace) paintFace(); Bangle.drawWidgets(); } }; if (Bangle.http && !menu){ Bangle.http("https://api.home.dns.t0.vc/menu", {timeout:3000}).then(event => { menu = JSON.parse(event.resp); require("Storage").writeJSON("menu.json", menu); }).catch((e)=>{ myMessage = "Menu error"; if (paintFace) paintFace(); }); } Bangle.on('swipe', handleSwipe); //Bangle.on('drag', handleDrag); Bangle.on('touch', handleTouch); Bangle.on('twist', handleTwist); // Show launcher when middle button pressed Bangle.setUI({ mode : "clock", remove : function() { // Called to unload all of the clock app Bangle.removeListener('swipe', handleSwipe); //Bangle.removeListener('drag', handleDrag); Bangle.removeListener('touch', handleTouch); Bangle.removeListener('twist', handleTwist); if (drawTimer) clearTimeout(drawTimer); drawTimer = undefined; if (stopWatchTimer) clearTimeout(stopWatchTimer); stopWatchTimer = undefined; paintFace = undefined; // http request may resolve after font's been unloaded, so unset }}); // Load widgets Bangle.loadWidgets(); paintFace(); drawStopWatches(); if (stopWatch.start1 || stopWatch.start2) { if (!stopWatchTimer) { stopWatchTimer = setInterval(drawStopWatches, 100); } } draw(); setTimeout(Bangle.drawWidgets,0); }