From aa91d43fa9a37e97653355c2880b308d93c4fa38 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 3 Feb 2023 12:49:54 +0100 Subject: [PATCH 01/17] qcenter - Cleanup timeout --- apps/qcenter/ChangeLog | 1 + apps/qcenter/app.js | 1 + apps/qcenter/metadata.json | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/qcenter/ChangeLog b/apps/qcenter/ChangeLog index 366b0ff86..436949dc9 100644 --- a/apps/qcenter/ChangeLog +++ b/apps/qcenter/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Fix fast loading on swipe to clock 0.03: Adds a setting for going back to clock on a timeout +0.04: Fix timeouts closing fast loaded apps \ No newline at end of file diff --git a/apps/qcenter/app.js b/apps/qcenter/app.js index f012fdda8..bd22c87e1 100644 --- a/apps/qcenter/app.js +++ b/apps/qcenter/app.js @@ -111,6 +111,7 @@ let layout = new Layout({ remove: ()=>{ Bangle.removeListener("swipe", onSwipe); Bangle.removeListener("touch", updateTimeout); + if (timeout) clearTimeout(timeout); delete Graphics.prototype.setFont8x12; } }); diff --git a/apps/qcenter/metadata.json b/apps/qcenter/metadata.json index 630fd2bef..cd3e350a4 100644 --- a/apps/qcenter/metadata.json +++ b/apps/qcenter/metadata.json @@ -2,7 +2,7 @@ "id": "qcenter", "name": "Quick Center", "shortName": "QCenter", - "version": "0.03", + "version": "0.04", "description": "An app for quickly launching your favourite apps, inspired by the control centres of other watches.", "icon": "app.png", "tags": "", From aedac6a4293b8a48c5e06dbd108dbab82895a96c Mon Sep 17 00:00:00 2001 From: CarlR9 <108166078+CarlR9@users.noreply.github.com> Date: Sat, 4 Feb 2023 16:05:00 +1300 Subject: [PATCH 02/17] Add files via upload --- apps/tempgraph/ChangeLog | 2 +- apps/tempgraph/app.js | 789 +++++++++++++++++++-------------------- 2 files changed, 395 insertions(+), 396 deletions(-) diff --git a/apps/tempgraph/ChangeLog b/apps/tempgraph/ChangeLog index 58dd75a19..d21f32e9a 100644 --- a/apps/tempgraph/ChangeLog +++ b/apps/tempgraph/ChangeLog @@ -1,2 +1,2 @@ 0.01: 3/Feb/2023 Added 'Temperature Graph' app to depository. - +0.02: 4/Feb/2023 Rewrote the widget handling after discovering there's a 'widget_utils' module to properly hide and show them. diff --git a/apps/tempgraph/app.js b/apps/tempgraph/app.js index a0bb3016b..d88222112 100644 --- a/apps/tempgraph/app.js +++ b/apps/tempgraph/app.js @@ -1,395 +1,394 @@ -// Temperature Graph -// BangleJS Script - -Bangle.setBarometerPower(true,"tempgraph"); -Bangle.loadWidgets(); -var wids=WIDGETS; -var widsOn=true; -var rm=null; -var gt=null; -var dg=null; -var Layout=require("Layout"); -var C=true; -var temp,tempMode,readErrCnt,watchButton2; - -var graph=require("Storage").readJSON("tempgraph.json",true); -if(graph==undefined) { - graph=[]; -} - -var timesData=[ - // dur=duration, u=time units, d=divisions on graph, s=seconds per unit. - {dur:10,u:"Mins",d:5,s:60}, - {dur:20,u:"Mins",d:4,s:60}, - {dur:30,u:"Mins",d:3,s:60}, - {dur:40,u:"Mins",d:4,s:60}, - {dur:1,u:"Hr",d:4,s:3600}, - {dur:2,u:"Hrs",d:4,s:3600}, - {dur:3,u:"Hrs",d:3,s:3600}, - {dur:4,u:"Hrs",d:4,s:3600}, - {dur:6,u:"Hrs",d:6,s:3600}, - {dur:8,u:"Hrs",d:4,s:3600}, - {dur:12,u:"Hrs",d:6,s:3600}, - {dur:16,u:"Hrs",d:4,s:3600}, - {dur:20,u:"Hrs",d:5,s:3600}, - {dur:1,u:"Day",d:4,s:3600}, - {dur:2,u:"Days",d:4,s:86400}, - {dur:3,u:"Days",d:3,s:86400}, - {dur:4,u:"Days",d:4,s:86400}, - {dur:5,u:"Days",d:5,s:86400}, - {dur:6,u:"Days",d:6,s:86400}, - {dur:7,u:"Days",d:7,s:86400} -]; -var times=[]; -for(n=0;n{ - temp=p.temperature; - if(tempMode=="drawGraph"&&graph.length>0&&Math.abs(graph[graph.length-1].temp-temp)>10&&readErrCnt<2){ - // A large change in temperature may be a reading error. ie. A 0C or less reading after - // a 20C reading. So if this happens, the reading is repeated up to 2 times to hopefully - // skip such errors. - readErrCnt++; - print("readErrCnt "+readErrCnt); - return; - } - clearInterval(gt); - readErrCnt=0; - switch (tempMode){ - case "showTemp": - showT(); - break; - case "drawGraph": - var date=new Date(); - var dateStr=require("locale").date(date).trim(); - var hrs=date.getHours(); - var mins=date.getMinutes(); - var secs=date.getSeconds(); - graph.push({ - temp:temp, - date:dateStr, - hrs:hrs, - mins:mins, - secs:secs - }); - if(graph.length==1){ - graph[0].dur=durInd; - } - require("Storage").writeJSON("tempgraph.json", graph); - if(graph.length==150){ - clearInterval(dg); - } - drawG(); - } - }); -} - -function getTemp(){ - readErrCnt=0; - gt = setInterval(getT,800); -} - -function setButton(){ - var watchButton=setWatch(function(){ - clearInterval(gt); - clearInterval(dg); - clearWatch(watchButton); - Bangle.removeListener("touch",screenTouch); - openMenu(); - },BTN); - Bangle.on('touch',screenTouch); -} - -function setButton2(){ - watchButton2=setWatch(function(){ - clearWatch(watchButton2); - openMenu(); - },BTN); -} - -function zPad(n){ - return n.toString().padStart(2,0); -} - -function screenTouch(n,ev){ - if(ev.y>23&&ev.y<152){ - C=C==false; - drawG(false); - } -} - -function drawG(){ - function cf(t){ - if(C){ - return t; - } - return getF(t); - } - drawWids(); - var top=1; - var bar=21; - var barBot=175-22; - if(widsOn){ - top=25; - bar=bar+24; - barBot=barBot-24; - } - var low=graph[0].temp; - var hi=low; - for(n=0;nt){ - low=t; - } - if(hi10){ - div=5; - } - if(C){ - g.setColor(1,0,0); - }else{ - g.setColor(0,0,1); - } - var step=(barBot-bar)/((tempHi-tempLow)/div); - for(n=0;nexit()}, - ],lazy:true - }); - drawWids(); - messageLO.render(); -} - -function showT(){ - tempLO.lab1.label=tempLO.lab3.label; - tempLO.lab2.label=tempLO.lab4.label; - tempLO.lab3.label=tempLO.lab5.label; - tempLO.lab4.label=tempLO.lab6.label; - tempLO.lab5.label=temp.toFixed(2)+"C"; - tempLO.lab6.label=getF(temp).toFixed(2)+"F"; - tempLO.render(); -} - -function exit(){ - clearWatch(watchButton2); - openMenu(); -} - -function showTemp(){ - tempMode="showTemp"; - setButton2(); - tempLO=new Layout({ - type:"v",c:[ - {type:"h",c:[ - {type:"txt",pad:5,col:"#f77",font:"6x8:2",label:" ",id:"lab1"}, - {type:"txt",pad:5,col:"#77f",font:"6x8:2",label:" ",id:"lab2"} - ]}, - {type:"h",c:[ - {type:"txt",pad:5,col:"#f77",font:"6x8:2",label:" ",id:"lab3"}, - {type:"txt",pad:5,col:"#77f",font:"6x8:2",label:" ",id:"lab4"} - ]}, - {type:"h",c:[ - {type:"txt",pad:5,col:"#f00",font:"6x8:2",label:" ",id:"lab5"}, - {type:"txt",pad:5,col:"#00f",font:"6x8:2",label:" ",id:"lab6"} - ]}, - {type:"h",c:[ - {type:"btn",pad:2,font:"6x8:2",label:"Temp",cb:l=>getTemp()}, - {type:"btn",pad:2,font:"6x8:2",label:"Exit",cb:l=>exit()} - ]} - ] - },{lazy:true}); - tempLO.render(); - getTemp(); -} - -var menu={ - "":{ - "title":" Temp. Graph" - }, - - "Widgets":{ - value:widsOn, - format:vis=>vis?"Hide":"Show", - onchange:vis=>{ - widsOn=vis; - refreshMenu(); - } - }, - - "Duration":{ - value:times.indexOf(duration), - min:0,max:times.length-1,step:1,wrap:true, - format:tim=>times[tim], - onchange:(dur)=>{ - duration=times[dur]; - } - }, - - "Draw Graph":function(){ - E.showMenu(); - drawGraph(); - }, - - "Show Graph" : function(){ - E.showMenu(); - if(graph.length>0){ - showGraph(); - }else{ - message("No graph to\nshow as no\ngraph has been\ndrawn yet."); - } - }, - - "Save Graph" : function(){ - E.showMenu(); - if(graph.length>0){ - saveGraph(); - }else{ - message("No graph to\nsave as no\ngraph has been\ndrawn yet."); - } - }, - - "Save Data" : function(){ - E.showMenu(); - if(graph.length>0){ - saveData(); - }else{ - message("No data to\nsave as no\ngraph has been\ndrawn yet."); - } - }, - - "Show Temp":function(){ - E.showMenu(); - showTemp(); - } -}; - -openMenu(); +// Temperature Graph +// BangleJS Script + +Bangle.setBarometerPower(true,"tempgraph"); +Bangle.loadWidgets(); +var widsOn=true; +var rm=null; +var gt=null; +var dg=null; +var Layout=require("Layout"); +var C=true; +var temp,tempMode,readErrCnt,watchButton2; + +var graph=require("Storage").readJSON("tempgraph.json",true); +if(graph==undefined) { + graph=[]; +} + +var timesData=[ + // dur=duration, u=time units, d=divisions on graph, s=seconds per unit. + {dur:10,u:"Mins",d:5,s:60}, + {dur:20,u:"Mins",d:4,s:60}, + {dur:30,u:"Mins",d:3,s:60}, + {dur:40,u:"Mins",d:4,s:60}, + {dur:1,u:"Hr",d:4,s:3600}, + {dur:2,u:"Hrs",d:4,s:3600}, + {dur:3,u:"Hrs",d:3,s:3600}, + {dur:4,u:"Hrs",d:4,s:3600}, + {dur:6,u:"Hrs",d:6,s:3600}, + {dur:8,u:"Hrs",d:4,s:3600}, + {dur:12,u:"Hrs",d:6,s:3600}, + {dur:16,u:"Hrs",d:4,s:3600}, + {dur:20,u:"Hrs",d:5,s:3600}, + {dur:1,u:"Day",d:4,s:3600}, + {dur:2,u:"Days",d:4,s:86400}, + {dur:3,u:"Days",d:3,s:86400}, + {dur:4,u:"Days",d:4,s:86400}, + {dur:5,u:"Days",d:5,s:86400}, + {dur:6,u:"Days",d:6,s:86400}, + {dur:7,u:"Days",d:7,s:86400} +]; +var times=[]; +for(n=0;n{ + temp=p.temperature; + if(tempMode=="drawGraph"&&graph.length>0&&Math.abs(graph[graph.length-1].temp-temp)>10&&readErrCnt<2){ + // A large change in temperature may be a reading error. ie. A 0C or less reading after + // a 20C reading. So if this happens, the reading is repeated up to 2 times to hopefully + // skip such errors. + readErrCnt++; + print("readErrCnt "+readErrCnt); + return; + } + clearInterval(gt); + readErrCnt=0; + switch (tempMode){ + case "showTemp": + showT(); + break; + case "drawGraph": + var date=new Date(); + var dateStr=require("locale").date(date).trim(); + var hrs=date.getHours(); + var mins=date.getMinutes(); + var secs=date.getSeconds(); + graph.push({ + temp:temp, + date:dateStr, + hrs:hrs, + mins:mins, + secs:secs + }); + if(graph.length==1){ + graph[0].dur=durInd; + } + require("Storage").writeJSON("tempgraph.json", graph); + if(graph.length==150){ + clearInterval(dg); + } + drawG(); + } + }); +} + +function getTemp(){ + readErrCnt=0; + gt = setInterval(getT,800); +} + +function setButton(){ + var watchButton=setWatch(function(){ + clearInterval(gt); + clearInterval(dg); + clearWatch(watchButton); + Bangle.removeListener("touch",screenTouch); + openMenu(); + },BTN); + Bangle.on('touch',screenTouch); +} + +function setButton2(){ + watchButton2=setWatch(function(){ + clearWatch(watchButton2); + openMenu(); + },BTN); +} + +function zPad(n){ + return n.toString().padStart(2,0); +} + +function screenTouch(n,ev){ + if(ev.y>23&&ev.y<152){ + C=C==false; + drawG(false); + } +} + +function drawG(){ + function cf(t){ + if(C){ + return t; + } + return getF(t); + } + drawWids(); + var top=1; + var bar=21; + var barBot=175-22; + if(widsOn){ + top=25; + bar=bar+24; + barBot=barBot-24; + } + var low=graph[0].temp; + var hi=low; + for(n=0;nt){ + low=t; + } + if(hi10){ + div=5; + } + if(C){ + g.setColor(1,0,0); + }else{ + g.setColor(0,0,1); + } + var step=(barBot-bar)/((tempHi-tempLow)/div); + for(n=0;nexit()}, + ],lazy:true + }); + drawWids(); + messageLO.render(); +} + +function showT(){ + tempLO.lab1.label=tempLO.lab3.label; + tempLO.lab2.label=tempLO.lab4.label; + tempLO.lab3.label=tempLO.lab5.label; + tempLO.lab4.label=tempLO.lab6.label; + tempLO.lab5.label=temp.toFixed(2)+"C"; + tempLO.lab6.label=getF(temp).toFixed(2)+"F"; + tempLO.render(); +} + +function exit(){ + clearWatch(watchButton2); + openMenu(); +} + +function showTemp(){ + tempMode="showTemp"; + setButton2(); + tempLO=new Layout({ + type:"v",c:[ + {type:"h",c:[ + {type:"txt",pad:5,col:"#f77",font:"6x8:2",label:" ",id:"lab1"}, + {type:"txt",pad:5,col:"#77f",font:"6x8:2",label:" ",id:"lab2"} + ]}, + {type:"h",c:[ + {type:"txt",pad:5,col:"#f77",font:"6x8:2",label:" ",id:"lab3"}, + {type:"txt",pad:5,col:"#77f",font:"6x8:2",label:" ",id:"lab4"} + ]}, + {type:"h",c:[ + {type:"txt",pad:5,col:"#f00",font:"6x8:2",label:" ",id:"lab5"}, + {type:"txt",pad:5,col:"#00f",font:"6x8:2",label:" ",id:"lab6"} + ]}, + {type:"h",c:[ + {type:"btn",pad:2,font:"6x8:2",label:"Temp",cb:l=>getTemp()}, + {type:"btn",pad:2,font:"6x8:2",label:"Exit",cb:l=>exit()} + ]} + ] + },{lazy:true}); + tempLO.render(); + getTemp(); +} + +var menu={ + "":{ + "title":" Temp. Graph" + }, + + "Widgets":{ + value:widsOn, + format:vis=>vis?"Hide":"Show", + onchange:vis=>{ + widsOn=vis; + refreshMenu(); + } + }, + + "Duration":{ + value:times.indexOf(duration), + min:0,max:times.length-1,step:1,wrap:true, + format:tim=>times[tim], + onchange:(dur)=>{ + duration=times[dur]; + } + }, + + "Draw Graph":function(){ + E.showMenu(); + drawGraph(); + }, + + "Show Graph" : function(){ + E.showMenu(); + if(graph.length>0){ + showGraph(); + }else{ + message("No graph to\nshow as no\ngraph has been\ndrawn yet."); + } + }, + + "Save Graph" : function(){ + E.showMenu(); + if(graph.length>0){ + saveGraph(); + }else{ + message("No graph to\nsave as no\ngraph has been\ndrawn yet."); + } + }, + + "Save Data" : function(){ + E.showMenu(); + if(graph.length>0){ + saveData(); + }else{ + message("No data to\nsave as no\ngraph has been\ndrawn yet."); + } + }, + + "Show Temp":function(){ + E.showMenu(); + showTemp(); + } +}; + +openMenu(); From 46c1ffa89311bbbb1aab22c85eec30d0b6be3cd9 Mon Sep 17 00:00:00 2001 From: CarlR9 <108166078+CarlR9@users.noreply.github.com> Date: Sat, 4 Feb 2023 19:05:16 +1300 Subject: [PATCH 03/17] Add files via upload --- apps/tempgraph/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tempgraph/metadata.json b/apps/tempgraph/metadata.json index 6772429a5..ceb6e565f 100644 --- a/apps/tempgraph/metadata.json +++ b/apps/tempgraph/metadata.json @@ -1,7 +1,7 @@ { "id": "tempgraph", "name": "Temperature Graph", "shortName":"Temp Graph", - "version":"0.01", + "version":"0.02", "description": "An app for recording the temperature for time periods ranging from 10 minutes to 7 days.", "icon": "app.png", "type": "app", From 12c75117820f164d9670e1afff3b162ce1e50e02 Mon Sep 17 00:00:00 2001 From: CarlR9 <108166078+CarlR9@users.noreply.github.com> Date: Sun, 5 Feb 2023 16:07:35 +1300 Subject: [PATCH 04/17] Add files via upload --- apps/tempgraph/ChangeLog | 1 + apps/tempgraph/app.js | 2 +- apps/tempgraph/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/tempgraph/ChangeLog b/apps/tempgraph/ChangeLog index d21f32e9a..74f2d7255 100644 --- a/apps/tempgraph/ChangeLog +++ b/apps/tempgraph/ChangeLog @@ -1,2 +1,3 @@ 0.01: 3/Feb/2023 Added 'Temperature Graph' app to depository. 0.02: 4/Feb/2023 Rewrote the widget handling after discovering there's a 'widget_utils' module to properly hide and show them. +0.03: 4/Feb/2023 Fixed number error in timesData array. diff --git a/apps/tempgraph/app.js b/apps/tempgraph/app.js index d88222112..b8dd231ae 100644 --- a/apps/tempgraph/app.js +++ b/apps/tempgraph/app.js @@ -31,7 +31,7 @@ var timesData=[ {dur:12,u:"Hrs",d:6,s:3600}, {dur:16,u:"Hrs",d:4,s:3600}, {dur:20,u:"Hrs",d:5,s:3600}, - {dur:1,u:"Day",d:4,s:3600}, + {dur:1,u:"Day",d:4,s:86400}, {dur:2,u:"Days",d:4,s:86400}, {dur:3,u:"Days",d:3,s:86400}, {dur:4,u:"Days",d:4,s:86400}, diff --git a/apps/tempgraph/metadata.json b/apps/tempgraph/metadata.json index ceb6e565f..63d4feddd 100644 --- a/apps/tempgraph/metadata.json +++ b/apps/tempgraph/metadata.json @@ -1,7 +1,7 @@ { "id": "tempgraph", "name": "Temperature Graph", "shortName":"Temp Graph", - "version":"0.02", + "version":"0.03", "description": "An app for recording the temperature for time periods ranging from 10 minutes to 7 days.", "icon": "app.png", "type": "app", From f4f07806a66cbd48d65857786de9944967f18161 Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 19:14:35 -0700 Subject: [PATCH 05/17] Added mtnclock support for reading weather.json This allows the use of owmweather or weather to provide weather updates to mtnclock. --- apps/mtnclock/app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js index 28ba25882..dedf60cfd 100644 --- a/apps/mtnclock/app.js +++ b/apps/mtnclock/app.js @@ -323,6 +323,11 @@ function setWeather() { draw(a); } +function readWeather() { + data = require("Storage").readJSON('weather.json').weather; + require("Storage").write('mtnclock.json', data); +} + const _GB = global.GB; global.GB = (event) => { if (event.t==="weather") { @@ -340,6 +345,7 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; + readWeather(); setWeather(); queueDraw(); }, 60000 - (Date.now() % 60000)); From 5c3b742a4275361656b734cda6037e2d68a4be25 Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 20:18:37 -0700 Subject: [PATCH 06/17] Prevent exceptions if weather.json doesn't exist. --- apps/mtnclock/app.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js index dedf60cfd..82d06e03b 100644 --- a/apps/mtnclock/app.js +++ b/apps/mtnclock/app.js @@ -324,8 +324,13 @@ function setWeather() { } function readWeather() { - data = require("Storage").readJSON('weather.json').weather; - require("Storage").write('mtnclock.json', data); + var weatherData = require("Storage").readJSON('weather.json', true); + if (weatherData !== undefined) { + if (weatherData.weather.time > data.time) { + data = weatherData.weather; + require("Storage").write('mtnclock.json', data); + } + } } const _GB = global.GB; From 3371f86bb5b8335d4d312ce7ca1d8ce967fc818b Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 21:39:43 -0700 Subject: [PATCH 07/17] Save minimal weather data and limit weather update frequency --- apps/mtnclock/app.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js index 82d06e03b..996fe2cee 100644 --- a/apps/mtnclock/app.js +++ b/apps/mtnclock/app.js @@ -324,19 +324,26 @@ function setWeather() { } function readWeather() { - var weatherData = require("Storage").readJSON('weather.json', true); - if (weatherData !== undefined) { - if (weatherData.weather.time > data.time) { - data = weatherData.weather; - require("Storage").write('mtnclock.json', data); - } + var weatherJson = require("Storage").readJSON('weather.json', 1); + // save updated weather data if available and it has been an hour since last updated + if (weatherJson !== undefined && (data.time === undefined || (data.time + 3600000) < weatherJson.weather.time)) { + data = { + time: weatherJson.weather.time, + temp: weatherJson.weather.temp, + code: weatherJson.weather.code + }; + require("Storage").writeJSON('mtnclock.json', data); } } const _GB = global.GB; global.GB = (event) => { if (event.t==="weather") { - data = event; + data = { + temp: event.temp, + code: event.code, + time: Date.now() + }; require("Storage").write('mtnclock.json', event); setWeather(); } @@ -357,5 +364,6 @@ function queueDraw() { } queueDraw(); +readWeather(); setWeather(); Bangle.setUI("clock"); From 653756c9172976d10a8098e780db694c1a231f49 Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 21:48:53 -0700 Subject: [PATCH 08/17] Updated version and README --- apps/mtnclock/README.md | 2 +- apps/mtnclock/metadata.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mtnclock/README.md b/apps/mtnclock/README.md index 58538509d..066230d4e 100644 --- a/apps/mtnclock/README.md +++ b/apps/mtnclock/README.md @@ -4,7 +4,7 @@ Based on the Pebble watchface Weather Land. Mountain Pass Clock changes depending on time (day/night) and weather conditions. -This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification). To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. +This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification), or a Bangle app that will update weather.kson such as OWM Weather. To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. The scene will change according to the following OpenWeatherMap conditions: clear, cloudy, overcast, lightning, drizzle, rain, fog and snow. Each weather condition has night/day scenes. diff --git a/apps/mtnclock/metadata.json b/apps/mtnclock/metadata.json index a3a173069..82a0cccab 100644 --- a/apps/mtnclock/metadata.json +++ b/apps/mtnclock/metadata.json @@ -2,7 +2,7 @@ "id": "mtnclock", "name": "Mountain Pass Clock", "shortName": "Mtn Clock", - "version": "0.01", + "version": "0.02", "description": "A clock that changes scenery based on time and weather.", "readme":"README.md", "icon": "app.png", From 959e376f099fce0dedca47b43ff97c970c2f5637 Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 21:57:52 -0700 Subject: [PATCH 09/17] Fixed typo --- apps/mtnclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mtnclock/README.md b/apps/mtnclock/README.md index 066230d4e..441754b83 100644 --- a/apps/mtnclock/README.md +++ b/apps/mtnclock/README.md @@ -4,7 +4,7 @@ Based on the Pebble watchface Weather Land. Mountain Pass Clock changes depending on time (day/night) and weather conditions. -This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification), or a Bangle app that will update weather.kson such as OWM Weather. To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. +This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification), or a Bangle app that will update weather.json such as OWM Weather. To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. The scene will change according to the following OpenWeatherMap conditions: clear, cloudy, overcast, lightning, drizzle, rain, fog and snow. Each weather condition has night/day scenes. From b2b299efc35e80ef23e07e22df62ed3e6abc38ee Mon Sep 17 00:00:00 2001 From: Sam Sorensen <825813+sabrsorensen@users.noreply.github.com> Date: Sun, 5 Feb 2023 21:59:29 -0700 Subject: [PATCH 10/17] Updated minimal weather data save from GB --- apps/mtnclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js index 996fe2cee..c6adc7706 100644 --- a/apps/mtnclock/app.js +++ b/apps/mtnclock/app.js @@ -344,7 +344,7 @@ global.GB = (event) => { code: event.code, time: Date.now() }; - require("Storage").write('mtnclock.json', event); + require("Storage").writeJSON('mtnclock.json', data); setWeather(); } if (_GB) setTimeout(_GB, 0, event); From d426ca3656591417fa82b07c6229d53c9770d843 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 6 Feb 2023 11:20:36 +0000 Subject: [PATCH 11/17] assistedgps 0.05: Fix regression in 0.04 that caused AGPS data not to get loaded --- apps/assistedgps/ChangeLog | 1 + apps/assistedgps/custom.html | 2 +- apps/assistedgps/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/assistedgps/ChangeLog b/apps/assistedgps/ChangeLog index ff2de6f67..92f04dc6d 100644 --- a/apps/assistedgps/ChangeLog +++ b/apps/assistedgps/ChangeLog @@ -2,3 +2,4 @@ 0.02: Update to work with Bangle.js 2 0.03: Select GNSS systems to use for Bangle.js 2 0.04: Now turns GPS off after upload +0.05: Fix regression in 0.04 that caused AGPS data not to get loaded diff --git a/apps/assistedgps/custom.html b/apps/assistedgps/custom.html index 75a4ecf32..716865983 100644 --- a/apps/assistedgps/custom.html +++ b/apps/assistedgps/custom.html @@ -158,7 +158,7 @@ var chunk = bin.substr(i,chunkSize); js += `\x10Serial1.write(atob("${btoa(chunk)}"))\n`; } - js = "\x10setTimeout(() => Bangle.setGPSPower(0,'agps'), 1000);\n"; // turn GPS off after a delay + js += "\x10setTimeout(() => Bangle.setGPSPower(0,'agps'), 1000);\n"; // turn GPS off after a delay return js; } diff --git a/apps/assistedgps/metadata.json b/apps/assistedgps/metadata.json index ac9fe5725..d2e7334c4 100644 --- a/apps/assistedgps/metadata.json +++ b/apps/assistedgps/metadata.json @@ -1,7 +1,7 @@ { "id": "assistedgps", "name": "Assisted GPS Updater (AGPS)", - "version": "0.04", + "version": "0.05", "description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", "sortorder": -1, "icon": "app.png", From ecf029deff3db61a8ce7dd5fa8e16087145631de Mon Sep 17 00:00:00 2001 From: Gabriele Monaco Date: Mon, 6 Feb 2023 18:01:04 +0100 Subject: [PATCH 12/17] agenda: show day of the week in date --- apps/agenda/ChangeLog | 1 + apps/agenda/agenda.js | 29 +++++++++++++++++------------ apps/agenda/metadata.json | 2 +- lang/it_IT.json | 10 +++++++++- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/apps/agenda/ChangeLog b/apps/agenda/ChangeLog index 99c44a2b1..9e7151e1e 100644 --- a/apps/agenda/ChangeLog +++ b/apps/agenda/ChangeLog @@ -12,3 +12,4 @@ 0.11: Setting to use "Today" and "Yesterday" instead of dates Added dynamic, short and range fields to clkinfo 0.12: Added color field and updating clkinfo periodically (running events) +0.13: Show day of the week in date diff --git a/apps/agenda/agenda.js b/apps/agenda/agenda.js index 8afca95a9..6d2b783fd 100644 --- a/apps/agenda/agenda.js +++ b/apps/agenda/agenda.js @@ -34,8 +34,9 @@ function getDate(timestamp) { return new Date(timestamp*1000); } function formatDay(date) { + let formattedDate = Locale.dow(date,1) + " " + Locale.date(date).replace(/\d\d\d\d/,""); if (!settings.useToday) { - return Locale.date(date); + return formattedDate; } const dateformatted = date.toISOString().split('T')[0]; // yyyy-mm-dd const today = new Date(Date.now()).toISOString().split('T')[0]; // yyyy-mm-dd @@ -46,7 +47,7 @@ function formatDay(date) { if (dateformatted == tomorrow) { return /*LANG*/"Tomorrow "; } - return Locale.date(date); + return formattedDate; } } function formatDateLong(date, includeDay, allDay) { @@ -58,7 +59,7 @@ function formatDateLong(date, includeDay, allDay) { return shortTime; } function formatDateShort(date, allDay) { - return formatDay(date).replace(/\d\d\d\d/,"")+(allDay?"":Locale.time(date,1)+Locale.meridian(date)); + return formatDay(date)+(allDay?"":Locale.time(date,1)+Locale.meridian(date)); } var lines = []; @@ -75,25 +76,29 @@ function showEvent(ev) { if (titleCnt) lines.push(""); // add blank line after title if(start.getDay() == end.getDay() && start.getMonth() == end.getMonth()) includeDay = false; - if(includeDay || ev.allDay) { + if(includeDay && ev.allDay) { + //single day all day (average to avoid getting previous day) lines = lines.concat( - /*LANG*/"Start:", + g.wrapString(formatDateLong(new Date((start+end)/2), includeDay, ev.allDay), g.getWidth()-10)); + } else if(includeDay || ev.allDay) { + lines = lines.concat( + /*LANG*/"Start"+":", g.wrapString(formatDateLong(start, includeDay, ev.allDay), g.getWidth()-10), - /*LANG*/"End:", + /*LANG*/"End"+":", g.wrapString(formatDateLong(end, includeDay, ev.allDay), g.getWidth()-10)); } else { lines = lines.concat( - g.wrapString(Locale.date(start), g.getWidth()-10), + g.wrapString(formatDateShort(start,true), g.getWidth()-10), g.wrapString(/*LANG*/"Start"+": "+formatDateLong(start, includeDay, ev.allDay), g.getWidth()-10), g.wrapString(/*LANG*/"End"+": "+formatDateLong(end, includeDay, ev.allDay), g.getWidth()-10)); } if(ev.location) - lines = lines.concat(/*LANG*/"Location"+": ", g.wrapString(ev.location, g.getWidth()-10)); - if(ev.description) + lines = lines.concat("",/*LANG*/"Location"+": ", g.wrapString(ev.location, g.getWidth()-10)); + if(ev.description && ev.description.trim()) lines = lines.concat("",g.wrapString(ev.description, g.getWidth()-10)); if(ev.calName) - lines = lines.concat(/*LANG*/"Calendar"+": ", g.wrapString(ev.calName, g.getWidth()-10)); - lines = lines.concat(["",/*LANG*/"< Back"]); + lines = lines.concat("",/*LANG*/"Calendar"+": ", g.wrapString(ev.calName, g.getWidth()-10)); + lines = lines.concat("",/*LANG*/"< Back"); E.showScroller({ h : g.getFontHeight(), // height of each menu item in pixels c : lines.length, // number of menu items @@ -120,7 +125,7 @@ function showList() { CALENDAR = CALENDAR.filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000); } if(CALENDAR.length == 0) { - E.showMessage("No events"); + E.showMessage(/*LANG*/"No events"); return; } E.showScroller({ diff --git a/apps/agenda/metadata.json b/apps/agenda/metadata.json index 88dd2c1bc..737568cb5 100644 --- a/apps/agenda/metadata.json +++ b/apps/agenda/metadata.json @@ -1,7 +1,7 @@ { "id": "agenda", "name": "Agenda", - "version": "0.12", + "version": "0.13", "description": "Simple agenda", "icon": "agenda.png", "screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}], diff --git a/lang/it_IT.json b/lang/it_IT.json index 310af8580..72d7dbb51 100644 --- a/lang/it_IT.json +++ b/lang/it_IT.json @@ -200,7 +200,15 @@ "Green": "Verde", "Blue": "Blu", "Black": "Nero", - "Show Week Number": "Mostra numero settimana" + "Show Week Number": "Mostra numero settimana", + "Calendar": "Calendario", + "Start": "Inizio", + "End": "Fine", + "Location": "Posizione", + "No location": "Nessuna posizione", + "No events": "Nessun evento", + "Today": "Oggi", + "Tomorrow": "Domani" }, "//2": "App-specific overrides", "alarm": { From db9bc005104523e8acfc8dbc7b168fce218094e5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Feb 2023 09:29:40 +0000 Subject: [PATCH 13/17] fix sanity check warning --- apps/mtnclock/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/mtnclock/ChangeLog diff --git a/apps/mtnclock/ChangeLog b/apps/mtnclock/ChangeLog new file mode 100644 index 000000000..cbf5c7f40 --- /dev/null +++ b/apps/mtnclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Get weather from weather.json From 489c96d9baaf2a85dd7f2185f9e6bf1a6aebb85a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 8 Feb 2023 09:30:07 +0000 Subject: [PATCH 14/17] Add LEGO remote control --- apps/legoremote/ChangeLog | 1 + apps/legoremote/README.md | 28 ++++++++++++++ apps/legoremote/app-icon.js | 1 + apps/legoremote/app.js | 70 ++++++++++++++++++++++++++++++++++ apps/legoremote/app.png | Bin 0 -> 14820 bytes apps/legoremote/metadata.json | 14 +++++++ 6 files changed, 114 insertions(+) create mode 100644 apps/legoremote/ChangeLog create mode 100644 apps/legoremote/README.md create mode 100644 apps/legoremote/app-icon.js create mode 100644 apps/legoremote/app.js create mode 100644 apps/legoremote/app.png create mode 100644 apps/legoremote/metadata.json diff --git a/apps/legoremote/ChangeLog b/apps/legoremote/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/legoremote/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/legoremote/README.md b/apps/legoremote/README.md new file mode 100644 index 000000000..a95b7b154 --- /dev/null +++ b/apps/legoremote/README.md @@ -0,0 +1,28 @@ +# LEGO Remote control + +This app allows you to control LEGO models from Bangle.js + +Right now the only supported control device is the Mould King M-0006 +Bluetooth remote for LEGO Power Functions: http://www.espruino.com/LEGO+Power+Functions+Clone + +LEGO Power Functions does not have an official Bluetooth remote controller. Hopefully +in the future this app will be able to support other types of remote (see below). + +## Usage + +Run the app, and ensure you're not connected to your watch via Bluetooth +(a warning will pop up if so). + +Now press the arrow keys on the screen to control the robot. + +It is expected that the robot is controlled by two motors, one on the left +side (connected to the `A` output) and one on the right (connected to the `B` output). + +## Future additions + +In the future it would be great to add: + +* Recording a series of movements and playing them back +* Support for official LEGO bluetooth remotes (via [Pybricks](https://pybricks.com/)) +* Support for different robot styles and configurations +* Using the Bangle's compass (or even GPS) to allow better robot control. diff --git a/apps/legoremote/app-icon.js b/apps/legoremote/app-icon.js new file mode 100644 index 000000000..850e0eda6 --- /dev/null +++ b/apps/legoremote/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/8H5A4NH/4ABJf4A/AFMC1Uq1QABhWqBYYJDAAegBYWqxWogWohQBCBYWpqsVqoABytVBYUC0u5rf5rf1q/xtQLBhWW/t//2/AYVKBYWX/u//z3B3//rRGCr/1/+H/v9/1/BYn2/lT+v6/oXDlF/4//9/78/5F4epv/X//f7/3+v9I4Wp38b/9v7//+4LD0P/HgN/7f/EgMoBYOlJ4IACDAP1O4QLH6ibCBYI7Br/+qf/iwLC1NIquhq2lquprWAWQVVoNVgtU0NVlQLCZQ7XDbgLWJEgOCdgLZBdwgA/AH4AaA")) diff --git a/apps/legoremote/app.js b/apps/legoremote/app.js new file mode 100644 index 000000000..1c76a54a8 --- /dev/null +++ b/apps/legoremote/app.js @@ -0,0 +1,70 @@ +var lego = require("mouldking"); +lego.start(); +E.on('kill', () => { + // return to normal Bluetooth advertising + NRF.setAdvertising({},{showName:true}); +}); +// You must leave one second after 'start' to allow the remote to be paired + +var arrowIcon = atob("IiiBAAAAwAAAAPwAAAB/gAAAP/AAAB/+AAAP/8AAB//4AAP//wAA///gAH///AA///8AH///4A////wH////gf////D////8f////5/////n////+f////4AP/8AAA//wAAD//AAAP/8AAA//wAAD//AAAH/8AAAf/wAAB//AAAH/8AAAf/gAAB/+AAAH/4AAAf/gAAB/+AAAH/4AAAP/gAAA/+AAAD/wAAAD8AA"); +var controlState = ""; + +Bangle.loadWidgets(); +Bangle.drawWidgets(); +var R = Bangle.appRect; +// we'll divide up into 3x3 +function getBoxCoords(x,y) { + return { + x : R.x + R.w*x/3, + y : R.y + R.h*y/3 + }; +} + +function draw() { + g.reset().clearRect(R); + var c, ninety = Math.PI/2; + var colOn = "#f00", colOff = g.theme.fg; + c = getBoxCoords(1.5, 0.5); + g.setColor(controlState=="up"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:0}); + c = getBoxCoords(2.5, 1.5); + g.setColor(controlState=="right"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:ninety}); + c = getBoxCoords(0.5, 1.5); + g.setColor(controlState=="left"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:-ninety}); + c = getBoxCoords(1.5, 1.5); + g.setColor(controlState=="down"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:ninety*2}); + if (NRF.getSecurityStatus().connected) { + c = getBoxCoords(1.5, 2.5); + g.setFontAlign(0,0).setFont("6x8").drawString("WARNING:\nBluetooth Connected\nYou must disconnect\nbefore LEGO will work",c.x,c.y); + } +} +draw(); +NRF.on('connect', draw); +NRF.on('disconnect', draw); + +function setControlState(s) { + controlState = s; + var c = {}; + var speed = 3; + if (s=="up") c={a:-speed,b:-speed}; + if (s=="down") c={a:speed,b:speed}; + if (s=="left") c={a:speed,b:-speed}; + if (s=="right") c={a:-speed,b:speed}; + draw(); + lego.set(c); +} + +Bangle.on('drag',e => { + var x = Math.floor(E.clip((e.x - R.x) * 3 / R.w,0,2.99)); + var y = Math.floor(E.clip((e.y - R.y) * 3 / R.h,0,2.99)); + if (!e.b) { + setControlState(""); + return; + } + if (y==0) { // top row + if (x==1) setControlState("up"); + } else if (y==1) { + if (x==0) setControlState("left"); + if (x==1) setControlState("down"); + if (x==2) setControlState("right"); + } +}); diff --git a/apps/legoremote/app.png b/apps/legoremote/app.png new file mode 100644 index 0000000000000000000000000000000000000000..727049e2ba713fe02ab9bcf97e8a9c52e0168b96 GIT binary patch literal 14820 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

3Dbt{R;TUJo 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 Date: Wed, 8 Feb 2023 13:59:38 +0100 Subject: [PATCH 15/17] Change colour Changes the to yellow on < 50% and red on < 20% battery percentage. --- apps/widbat/widget.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/widbat/widget.js b/apps/widbat/widget.js index a8a0c5382..7fce16335 100644 --- a/apps/widbat/widget.js +++ b/apps/widbat/widget.js @@ -31,7 +31,11 @@ x+=16; } g.setColor(g.theme.fg).fillRect(x,y+2,x+s-4,y+21).clearRect(x+2,y+4,x+s-6,y+19).fillRect(x+s-3,y+10,x+s,y+14); - g.setColor("#0f0").fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17); + var battery = E.getBattery(); + if(battery < 20) {g.setColor("#f00");} + else if (battery < 50) {g.setColor("#ff0");} + else {g.setColor("#0f0");} + g.fillRect(x+4,y+6,x+4+battery*(s-12)/100,y+17); }}; setWidth(); })() From 26589fa779c0a3a34679c36a214dbb4c14ffa1cb Mon Sep 17 00:00:00 2001 From: KungPhoo Date: Wed, 8 Feb 2023 14:06:46 +0100 Subject: [PATCH 16/17] Update ChangeLog --- apps/widbat/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/widbat/ChangeLog b/apps/widbat/ChangeLog index 5986ecf3f..59c58af32 100644 --- a/apps/widbat/ChangeLog +++ b/apps/widbat/ChangeLog @@ -6,3 +6,4 @@ 0.07: Move CHARGING variable to more readable string 0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on 0.09: Misc speed/memory tweaks +0.10: Color changes due to the battery level From 50a66490909fd7bbc2cb20c57e2e7a5196f81dd3 Mon Sep 17 00:00:00 2001 From: KungPhoo Date: Wed, 8 Feb 2023 14:10:10 +0100 Subject: [PATCH 17/17] Update version --- apps/widbat/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widbat/metadata.json b/apps/widbat/metadata.json index 993310eb2..5f0d1b7d1 100644 --- a/apps/widbat/metadata.json +++ b/apps/widbat/metadata.json @@ -1,7 +1,7 @@ { "id": "widbat", "name": "Battery Level Widget", - "version": "0.09", + "version": "0.10", "description": "Show the current battery level and charging status in the top right of the clock", "icon": "widget.png", "type": "widget",