diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index ecd0c355f..f9bc5e65a 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -6,4 +6,5 @@ 0.06: Design and usability improvements. 0.07: Improved positioning. 0.08: Select the color of widgets correctly. Additional settings to hide colon. -0.09: Larger font size if colon is hidden to improve readability further. \ No newline at end of file +0.09: Larger font size if colon is hidden to improve readability further. +0.10: HomeAssistant integration if HomeAssistant is installed. \ No newline at end of file diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index f6a1c6522..190488d6b 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -7,6 +7,7 @@ - Tab left/right of screen to show steps, temperature etc. - Enable / disable lock icon in the settings. - If the "sched" app is installed tab top / bottom of the screen to set the timer. +- If HomeAssistant is installed, triggers are shown. Simple select the trigger and touch the middle of the screen to send the trigger to HomeAssistant. - The design is adapted to the theme of your bangle. - The colon (e.g. 7:35 = 735) can be hidden now in the settings. diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 5bfec4097..4b7deb21e 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -62,86 +62,127 @@ Graphics.prototype.setMediumFont = function(scale) { Graphics.prototype.setSmallFont = function(scale) { // Actual height 28 (27 - 0) - this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//84D//zgP/+GAAAAAAAAAAAAAAAAAAAD4AAAPgAAA+AAAAAAAAAAAAA+AAAD4AAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAg4AAHDgAAcOCABw54AHD/gAf/8AD/8AB//gAP8OAA9w4YCHD/gAcf+AB//gAf/gAP/uAA/w4ADnDgAAcOAABw4AAHAAAAcAAAAAAAAAAAAAAAIAA+A4AH8HwA/4PgHjgOAcHAcBwcBw/BwH78DgfvwOB8HA4HAOBw8A+HngB4P8ADgfgAAAYAAAAAAAAAAB4AAAf4AQB/gDgOHAeA4cDwDhweAOHDwA88eAB/nwAD88AAAHgAAA8AAAHn4AA8/wAHnvgA8cOAHhg4A8GDgHgcOA8B74BgD/AAAH4AAAAAAAAAAAAAAAAAMAAAH8AD8/4Af/3wB/8HgODwOA4HA4DgODgOAcOA4A44DwDzgHAH8AMAPwAQP+AAA/8AAAB4AAADAAAAAA+AAAD4AAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8AD//+A/+/+H4AD98AAB3gAADIAAAAAAAAAAAAAIAAABwAAAXwAAHPwAB8P8D/gP//4AH/8AAAAAAAAAAAAAAAAAAAAAAAAGAAAA4gAAB/AAAH8AAD/AAAP8AAAH4AAAfwAADiAAAOAAAAAAAAAAAAAAGAAAAYAAABgAAAGAAAAYAAABgAAD/+AAP/4AABgAAAGAAAAYAAABgAAAGAAAAYAAAAAAAAAAAAAADkAAAPwAAA/AAAAAAAAAAAAAAAAAAAAAAAAABgAAAGAAAAYAAABgAAAGAAAAYAAABgAAAGAAAAYAAAAAAAAAAAAAAAAAAAAAAADgAAAOAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAA4AAA/gAA/+AA//AA//AAP/AAA/AAADAAAAAAAAAAAAAAAAAAA//gAP//gB///AHgA8A8AB4DgADgOAAOA4AA4DgADgPAAeAeADwB///AD//4AD/+AAAAAAAAAAAAAAAA4AAAHgAAAcAAADwAAAP//+A///4D///gAAAAAAAAAAAAAAAAAAAAAAYAeADgD4AeAfAD4DwAfgOAD+A4Ae4DgDzgOAeOA4Dw4DweDgH/wOAP+A4AfwDgAAAAAAAAAAAAIAOAA4A4ADwDggHAOHgOA48A4DnwDgO/AOA7uA4D84HgPh/8A8H/gDgH8AAACAAAAAAAAAAAAAHgAAB+AAA/4AAP7gAD+OAA/g4AP4DgA+AOADAA4AAB/+AAH/4AAf/gAADgAAAOAAAAAAAAAAAAAAAAD4cAP/h4A/+HwDw4HgOHAOA4cA4DhwDgOHAOA4cA4Dh4HAOD58A4H/gAAP8AAAGAAAAAAAAAAAAAAAAD/+AAf/8AD//4AePDwDw4HgOHAOA4cA4DhwDgOHAOA4cB4Bw8PAHD/8AIH/gAAH4AAAAAAAAAADgAAAOAAAA4AAYDgAHgOAD+A4B/wDgf4AOP+AA7/AAD/gAAP4AAA8AAAAAAAAAAAAAAAAAAeH8AD+/4Af//wDz8HgOHgOA4OA4Dg4DgODgOA4eA4Dz8HgH//8AP7/gAeH8AAAAAAAAAAAAAAAA+AAAH+AgB/8HAHh4cA8Dg4DgODgOAcOA4Bw4DgODgPA4eAeHDwB///AD//4AD/+AAAAAAAAAAAAAAAAAAAAAAAAAAODgAA4OAADg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAABwA5AHAD8AcAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAB8AAAP4AAB5wAAPDgAB4HAAHAOAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAEAAcA4AB4HAADw4AADnAAAH4AAAPAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAB8AAAHgAAA4AAADgDzgOA/OA4D84DgeAAPHwAAf+AAA/wAAB8AAAAAAAAAAAAAAAAAAD+AAB/+AAP/8AB4B4AOABwBwADgHB8OA4P4cDhxxwMGDDAwYMMDBgwwOHHHA4f4cDh/xwHAHCAcAMAA8AwAB8PAAD/4AAD/AAAAAAAAAAAAAACAAAB4AAB/gAA/8AAf+AAP/wAH/nAA/gcADwBwAPwHAA/4cAA/9wAAf/AAAP/AAAD/gAAB+AAAA4AAAAAAAAAAAAAAD///gP//+A///4DgcDgOBwOA4HA4DgcDgOBwOA4HA4Dg8DgPHwOAf/h4A///AB8f4AAAfAAAAAAAP+AAD/+AAf/8AD4D4AeADwBwAHAOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOAcABwB4APAD4D4AHgPAAOA4AAAAAAAAAAAAAAAP//+A///4D///gOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOA8AB4BwAHAHwB8AP//gAP/4AAP+AAAAAAAAAAAAAAAA///4D///gP//+A4HA4DgcDgOBwOA4HA4DgcDgOBwOA4HA4DgcDgOBgOA4AA4AAAAAAAAAAAAAAD///gP//+A///4DgcAAOBwAA4HAADgcAAOBwAA4HAADgcAAOAwAA4AAAAAAAAAf+AAD/+AA//+ADwB4AeADwDwAHgOAAOA4AA4DgADgOAAOA4AA4DgMDgPAweAcDBwB8MfADw/4AHD/AAAPwAAAAAAAAAAAAAAAP//+A///4D///gABwAAAHAAAAcAAABwAAAHAAAAcAAABwAAAHAAAAcAAABwAA///4D///gP//+AAAAAAAAAAAAAAAAAAAD///gP//+A///4AAAAAAAAAAAADgAAAPAAAA+AAAA4AAADgAAAOAAAA4AAAHgP//8A///wD//8AAAAAAAAAAAAAAAAAAAA///4D///gP//+AAHAAAA+AAAP8AAB54AAPDwAB4HgAPAPAB4AfAPAA+A4AA4DAABgAAACAAAAAAAAAAP//+A///4D///gAAAOAAAA4AAADgAAAOAAAA4AAADgAAAOAAAA4AAADgAAAAAAAAAAAAAAP//+A///4D///gD+AAAD+AAAB+AAAB/AAAB/AAAB/AAAB+AAAH4AAB+AAA/gAAP4AAD+AAA/AAAfwAAD///gP//+A///4AAAAAAAAAAAAAAAAAAAP//+A///4D///gHwAAAPwAAAPgAAAfgAAAfAAAAfAAAA/AAAA+AAAB+AAAB8A///4D///gP//+AAAAAAAAAAAP+AAD/+AAf/8AD4D4AeADwBwAHAOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOAcABwB4APAD4D4AH//AAP/4AAP+AAAAAAAAAAAP//+A///4D///gOAcAA4BwADgHAAOAcAA4BwADgHAAOAcAA4DgAD4eAAH/wAAP+AAAPgAAAAAAAA/4AAP/4AB//wAPgPgB4APAHAAcA4AA4DgADgOAAOA4AA4DgADgOAAOA4AO4BwA/AHgB8APgPwAf//gA//uAA/4QAAAAAAAAAA///4D///gP//+A4BwADgHAAOAcAA4BwADgHAAOAcAA4B8ADgP8APh/8Af/H4A/4HgA+AGAAAAAAAAAAAABgAHwHAA/g+AH/A8A8cBwDg4DgODgOA4OA4DgcDgOBwOA4HA4DwODgHg4cAPh/wAcH+AAwPwAAAAADgAAAOAAAA4AAADgAAAOAAAA4AAAD///gP//+A///4DgAAAOAAAA4AAADgAAAOAAAA4AAADgAAAAAAAAAAAAAAAAAP//AA///AD//+AAAB8AAABwAAADgAAAOAAAA4AAADgAAAOAAAA4AAAHgAAA8A///gD//8AP//gAAAAAAAAAAIAAAA8AAAD+AAAH/AAAD/wAAB/4AAA/8AAAf4AAAPgAAB+AAA/4AAf+AAP/AAH/gAD/wAAP4AAA4AAAAAAAAPAAAA/gAAD/4AAA/+AAAf/AAAH/gAAB+AAAf4AAf/AAf/AAP/gAD/gAAPwAAA/4AAA/+AAAf/AAAH/wAAB/gAAB+AAB/4AA/+AA/+AA/+AAD/AAAPAAAAgAAAAAAAAMAAGA4AA4D4APgHwB8APwfAAPn4AAf+AAAfwAAB/AAAf+AAD4+AA/B8AHwB8A+AD4DgADgMAAGAwAAADwAAAPwAAAPwAAAfgAAAfgAAAf/4AAf/gAH/+AB+AAAPwAAD8AAA/AAADwAAAMAAAAgAAAAAAAAMAACA4AA4DgAPgOAD+A4Af4DgH7gOB+OA4Pw4Dj8DgO/AOA/4A4D+ADgPgAOA4AA4DAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////////gAAAOAAAA4AAADAAAAAAAAAAAAAAAAAAAAAAA4AAAD+AAAP/gAAH/4AAB/+AAAf+AAAH4AAABgAAAAAAAAADAAAAOAAAA4AAADgAAAP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAADgAAAcAAADgAAAcAAADgAAAcAAAB4AAADwAAADgAAAHAAAAOAAAAYAAAAAAAAAAAAAAAAAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAHH8AA8/4AHzjgAcMOABxwYAHHBgAccOABxwwAHGHAAP/4AA//4AA//gAAAAAAAAAAAAAAAAAAA///4D///gP//+AA4BwAHADgAcAOABwA4AHADgAcAOAB4B4ADwPAAP/8AAf/AAAf4AAAAAAAAAAAAPwAAD/wAAf/gADwPAAeAeABwA4AHADgAcAOABwA4AHADgAeAeAA8DwABwOAADAwAAAAAAAAAAAA/AAAP/AAD//AAPA8AB4B4AHADgAcAOABwA4AHADgAcAOAA4BwD///gP//+A///4AAAAAAAAAAAAAAAAPwAAD/wAAf/gAD2PAAeYeABxg4AHGDgAcYOABxg4AHGDgAeYeAA/jwAB+OAAD4wAABgAAAAAAAAAAABgAAAGAAAB//+Af//4D///gPcAAA5gAADGAAAMYAAAAAAAAAPwAAD/wMA//w4DwPHgeAePBwA4cHADhwcAOHBwA4cHADhwOAcPB///4H///Af//wAAAAAAAAAAAAAAAAAAD///gP//+AA//4ADgAAAcAAABwAAAHAAAAcAAABwAAAHgAAAP/+AAf/4AA//gAAAAAAAAAAAAAAMf/+A5//4Dn//gAAAAAAAAAAAAAAAAAAHAAAAfn///+f//+5///wAAAAAAAAAAAAAAAAAAP//+A///4D///gAAcAAAD8AAAf4AADzwAAeHgAHwPAAeAeABgA4AEABgAAAAAAAAAD///gP//+A///4AAAAAAAAAAAAAAAAAAAAf/+AB//4AH//gAOAAABwAAAHAAAAcAAABwAAAHgAAAP/+AA//4AB//gAOAAABwAAAHAAAAcAAABwAAAHgAAAf/+AA//4AA//gAAAAAAAAAAAAAAAf/+AB//4AD//gAOAAABwAAAHAAAAcAAABwAAAHAAAAeAAAA//4AB//gAD/+AAAAAAAAAAAAAAAAD8AAA/8AAH/4AA8DwAHgHgAcAOABwA4AHADgAcAOABwA4AHgHgAPh8AAf/gAA/8AAA/AAAAAAAAAAAAAAAAB///8H///wf///A4BwAHADgAcAOABwA4AHADgAcAOAB4B4ADwPAAP/8AAf/AAAf4AAAAAAAAAAAAPwAAD/wAA//wADwPAAeAeABwA4AHADgAcAOABwA4AHADgAOAcAB///8H///wf///AAAAAAAAAAAAAAAAAAAH//gAf/+AB//4ADwAAAcAAABwAAAHAAAAcAAAAAAAAAAMAAHw4AA/jwAH+HgAcYOABxw4AHHDgAcMOABw44AHjjgAPH+AA8fwAAw+AAAAAABgAAAGAAAAcAAAf//wB///AH//+ABgA4AGADgAYAOABgA4AAAAAAAAAAAAAAAH/AAAf/wAB//wAAB/AAAAeAAAA4AAADgAAAOAAAA4AAADgAAAcAB//4AH//gAf/+AAAAAAAAAAAAAAABwAAAH4AAAf8AAAP8AAAH+AAAD+AAAD4AAA/gAAf8AAP+AAH/AAAfgAABwAAAAAAAAAAAABwAAAH8AAAf+AAAP/gAAD/gAAB+AAAf4AAP8AAP+AAB/AAAH4AAAf8AAAP+AAAD/gAAB+AAAf4AAf/AAP/AAB/gAAHgAAAQAAABAAIAHADgAeAeAA8HwAB8+AAD/gAAD8AAAPwAAD/gAAfPgADwfAAeAeABwA4AEAAgAAAAABAAAAHgAAAfwAAA/wAAAf4BwAP4/AAP/8AAP+AAD/AAB/wAA/4AAP8AAB+AAAHAAAAQAAAAAAIAHADgAcAeABwD4AHA/gAcHuABx84AHPDgAf4OAB/A4AHwDgAeAOABgA4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAH4Af//////n//AAAA4AAADgAAAAAAAAAAAAAAAAAP//+A///4D///gAAAAAAAAAAAAAAAAAAA4AAADgAAAOAAAA//5/9////wAH4AAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAeAAAD4AAAOAAAA4AAADgAAAHAAAAcAAAA4AAADgAAAOAAAD4AAAPAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 32, atob("BgkMGhEZEgYMDAwQCAwICxILEBAREBEOEREJCREVEQ8ZEhEUExAOFBQHDREPGBMUERQSEhEUERsREBIMCwwTEg4QERAREQoREQcHDgcYEREREQoPDBEPFg8PDwwIDBMc"), 28+(scale<<8)+(1<<16)); + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 32, + atob("BgkMGhEZEgYMDAwQCAwICxILEBAREBEOEREJCREVEQ8ZEhEUExAOFBQHDREPGBMUERQSEhEUERsREBIMCwwTEg4QERAREQoREQcHDgcYEREREQoPDBEPFg8PDwwIDBMcCgoAAAAAAAAAAAAAACERESEAAAAAAAAAAAAAAAAhIQAGCRAQEhAIDw8XCQ8RABIODRELCw4REwcLCQoPHBscDxISEhISEhoUEBAQEAcHBwcTExQUFBQUDhQUFBQUEBEREBAQEBAQGhARERERBwcHBxAREREREREPEREREREPEQ8="), + 28+(scale<<8)+(1<<16) + ); return this; }; -var imgLock = { - width : 16, height : 16, bpp : 1, - transparent : 0, - buffer : E.toArrayBuffer(atob("A8AH4A5wDDAYGBgYP/w//D/8Pnw+fD58Pnw//D/8P/w=")) -}; +function imgLock(){ + return { + width : 16, height : 16, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("A8AH4A5wDDAYGBgYP/w//D/8Pnw+fD58Pnw//D/8P/w=")) + } +} -var imgSteps = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/H///wv4CBn4CD8ACCj4IBj8f+Eeh/wjgCBngCCg/4nEH//4h/+jEP/gRBAQX+jkf/wgB//8GwP4FoICDHgICCBwIA==")) -}; +function imgSteps(){ + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/H///wv4CBn4CD8ACCj4IBj8f+Eeh/wjgCBngCCg/4nEH//4h/+jEP/gRBAQX+jkf/wgB//8GwP4FoICDHgICCBwIA==")) + } +} -var imgBattery = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AN4EAg4TBgd///9oEAAQv8ARQRDDQQgCEwQ4OA")) -}; +function imgBattery(){ + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/4AN4EAg4TBgd///9oEAAQv8ARQRDDQQgCEwQ4OA")) + } +} -var imgBpm = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AOn4CD/wCCjgCCv/8jF/wGYgOA5MB//BC4PDAQnjAQPnAQgANA")) -}; +function imgBpm() { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/4AOn4CD/wCCjgCCv/8jF/wGYgOA5MB//BC4PDAQnjAQPnAQgANA")) + } +} -var imgTemperature = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//D///wICBjACBngCNkgCP/0kv/+s1//nDn/8wICEBAIOC/08v//IYJECA==")) -}; +function imgTemperature() { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("//D///wICBjACBngCNkgCP/0kv/+s1//nDn/8wICEBAIOC/08v//IYJECA==")) + } +} -var imgWind = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/0f//8h///Pn//zAQXzwf/88B//mvGAh18gEevn/DIICB/PwgEBAQMHBAIADFwM/wEAGAP/54CD84CE+eP//wIQU/A==")) -}; +function imgWind () { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/0f//8h///Pn//zAQXzwf/88B//mvGAh18gEevn/DIICB/PwgEBAQMHBAIADFwM/wEAGAP/54CD84CE+eP//wIQU/A==")) + } +} -var imgTimer = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/+B/4CD84CEBAPygFP+F+h/x/+P+fz5/n+HnAQNn5/wuYCBmYCC5kAAQfOgFz80As/ngHn+fD54mC/F+j/+gF/HAQA==")) -}; +function imgTimer() { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/+B/4CD84CEBAPygFP+F+h/x/+P+fz5/n+HnAQNn5/wuYCBmYCC5kAAQfOgFz80As/ngHn+fD54mC/F+j/+gF/HAQA==")) + } +} -var imgCharging = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) -}; +function imgCharging() { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) + } +} -var imgWatch = { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC")) -}; +function imgWatch() { + return { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC")) + } +} /* * INFO ENTRIES + * List of [Data, Icon, left/right, HomeAssistant Trigger] */ var infoArray = [ - function(){ return [ null, null, "left" ] }, - function(){ return [ "Bangle", imgWatch, "right" ] }, - function(){ return [ E.getBattery() + "%", imgBattery, "left" ] }, - function(){ return [ getSteps(), imgSteps, "left" ] }, - function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm, "left"] }, - function(){ return [ getWeather().temp, imgTemperature, "left" ] }, - function(){ return [ getWeather().wind, imgWind, "left" ] }, + function(){ return [ null, null, "left", null ] }, + function(){ return [ "Bangle", imgWatch(), "right", null ] }, + function(){ return [ E.getBattery() + "%", imgBattery(), "left", null ] }, + function(){ return [ getSteps(), imgSteps(), "left", null ] }, + function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm(), "left", null] }, + function(){ return [ getWeather().temp, imgTemperature(), "left", null ] }, + function(){ return [ getWeather().wind, imgWind(), "left", null ] }, ]; + +/* + * We append the HomeAssistant integrations if HomeAssistant is available + */ +try{ + var triggers = require("ha.lib.js").getTriggers(); + triggers.forEach(trigger => { + infoArray.push(function(){ + return [trigger.display, trigger.getIcon(), "left", trigger.trigger] + }); + }) +} catch(ex){ + // Nothing to do if HomeAssistant is not available... +} const NUM_INFO=infoArray.length; function getInfoEntry(){ if(isAlarmEnabled()){ - return [getAlarmMinutes() + " min.", imgTimer, "left"] + return [getAlarmMinutes() + " min.", imgTimer(), "left", null] } else if(Bangle.isCharging()){ - return [E.getBattery() + "%", imgCharging, "left"] + return [E.getBattery() + "%", imgCharging(), "left", null] } else{ + // In case the user removes HomeAssistant entries, showInfo + // could be larger than infoArray.length... + settings.showInfo = settings.showInfo % infoArray.length; return infoArray[settings.showInfo](); } } @@ -351,12 +392,14 @@ function drawTime(){ g.setSmallFont(); var imgWidth = 0; if(infoImg !== undefined){ - imgWidth = infoImg.width; + imgWidth = 26.0; var strWidth = g.stringWidth(infoStr); + var scale = imgWidth / infoImg.width; g.drawImage( infoImg, - W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - infoImg.width/2, - y - infoImg.height/2 + W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - parseInt(imgWidth/2), + y - parseInt(imgWidth/2), + { scale: scale } ); } g.drawString(infoStr, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); @@ -366,7 +409,7 @@ function drawTime(){ function drawLock(){ if(settings.showLock && Bangle.isLocked()){ g.setColor(g.theme.fg); - g.drawImage(imgLock, W-16, 2); + g.drawImage(imgLock(), W-16, 2); } } @@ -429,6 +472,7 @@ Bangle.on('touch', function(btn, e){ var is_right = e.x > right; var is_upper = e.y < upper; var is_lower = e.y > lower; + var is_center = !is_upper && !is_lower && !is_left && !is_right; if(is_upper){ Bangle.buzz(40, 0.6); @@ -454,11 +498,34 @@ Bangle.on('touch', function(btn, e){ settings.showInfo = settings.showInfo < 0 ? NUM_INFO-1 : settings.showInfo; drawTime(); } + + if(is_center){ + var infoEntry = getInfoEntry(); + var trigger = infoEntry[3]; + if(trigger != null){ + try{ + require("ha.lib.js").sendTrigger("TRIGGER_BW"); + Bangle.buzz(80, 0.6).then(()=>{ + require("ha.lib.js").sendTrigger(trigger); + setTimeout(()=>{ + Bangle.buzz(80, 0.6); + }, 250); + }); + }catch(ex){ + print(ex); + // Without ha -> nop. + } + } + } }); E.on("kill", function(){ - storage.write(SETTINGS_FILE, settings); + try{ + storage.write(SETTINGS_FILE, settings); + } catch(ex){ + // If this fails, we still kill the app... + } }); diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index eba1449a6..95fb7e608 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,11 +1,11 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.09", + "version": "0.10", "description": "BW Clock.", "readme": "README.md", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}, {"url":"screenshot_3.png"}], + "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}, {"url":"screenshot_3.png"}, {"url":"screenshot_4.png"}], "type": "clock", "tags": "clock", "supports": ["BANGLEJS2"], diff --git a/apps/bwclk/screenshot_4.png b/apps/bwclk/screenshot_4.png new file mode 100644 index 000000000..3807d47ad Binary files /dev/null and b/apps/bwclk/screenshot_4.png differ diff --git a/apps/ha/ChangeLog b/apps/ha/ChangeLog index 07afedd21..e78b4ccd0 100644 --- a/apps/ha/ChangeLog +++ b/apps/ha/ChangeLog @@ -1 +1,2 @@ -0.01: Release \ No newline at end of file +0.01: Release +0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. \ No newline at end of file diff --git a/apps/ha/README.md b/apps/ha/README.md index 8005421f1..654a262c8 100644 --- a/apps/ha/README.md +++ b/apps/ha/README.md @@ -1,13 +1,15 @@ # Home Assistant This app integrates your BangleJs into the HomeAssistant. + # How to use Click on the left and right side of the screen to select the triggers that you configured. Click in the middle of the screen to send the trigger to HomeAssistant. ![](screenshot.png) -# First Setup + +# Initial Setup 1.) First of all, make sure that HomeAssistant and the HomeAssistant Android App works. 2.) Open your BangleJs Gadgetbridge App, click on the Settings icon of your BangleJs and enable "Allow Intent Access" @@ -22,6 +24,7 @@ configured. Click in the middle of the screen to send the trigger to HomeAssista This setup must be done only once -- now you are ready to configure your BangleJS to control some devices or entities in your HomeAssistant :) + # Setup Trigger 1.) Upload the app and all corresponding triggers through the AppStore UI. You must specify the display name, the trigger as well as an icon. @@ -38,12 +41,36 @@ The following icons are currently supported: 3.) Don't forget to select the action that should be executed at the bottom of each automation. + # Default Trigger This app also implements two default trigger that can always be used: - APP_STARTED -- Will be sent whenever the app is started. So you could do some actions already when the app is sarted without the need of any user interaction. - TRIGGER -- Will be sent whenever some trigger is executed. So you could generically listen to that. +# How to use the library (ha.lib.js) in my own app/clk +This app inlcludes a library that can be used by other apps or clocks +to read all configured intents or to send a trigger. Example code: + +```js +// First of all impport the library +var ha = require("ha.lib.js"); + +// You can read all triggers that a user configured simply via +var triggers = ha.getTriggers(); + +// Get display name and icon of trigger +var display = triggers[0].display; +var icon = triggers[0].getIcon(); + +// Trigger the first configured trigger +ha.sendTrigger(triggers[0].trigger); + +// Send a custom trigger that is not configured by a user +ha.sendTrigger("MY_CUSTOM_TRIGGER"); +``` + + # FAQ ## Sometimes the trigger is not executed diff --git a/apps/ha/ha.app.js b/apps/ha/ha.app.js index 85f926138..d9199fb0e 100644 --- a/apps/ha/ha.app.js +++ b/apps/ha/ha.app.js @@ -1,72 +1,10 @@ -var storage = require("Storage"); +/** + * This app uses the ha library to send trigger to HomeAssistant. + */ +var ha = require("ha.lib.js"); var W = g.getWidth(), H = g.getHeight(); var position=0; - - -// Note: All icons should have 48x48 pixels -function getIcon(icon){ - if(icon == "light"){ - return { - width : 48, height : 48, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAMBwAFE4AFDgYFJjgFBnAFBjwXBvAFBh4jBuAFCAQPwAQMHAQPgEQQCBEgcf/AvDn/8Aof//5GDAoJOBh+BAoOB+EP8YFB4fwgfnAoPnGANHAoPjHYQFBHYQFd44pDg47C4/gh/DIIZNFLIplGgF//wFIgZ9BRIUHRII7Ch4FBUIUOAoKzCjwFEhgCBmDpIVooFFh4oCAA4LFC5b7BAob1BAYI=")) - }; - } else if(icon == "door"){ - return { - width : 48, height : 48, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAM4Aok/4AED///Aov4Aon8DgQGBAv4FpnIFKJv4FweAQFFAgQFB8AFDnADC")) - }; - } else if (icon == "fire"){ - return { - width : 48, height : 48, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("ABsDAokBwAFE4AFE8AFE+AFE/AFJgf8Aon+AocHAokP/8QAokYAoUfAok//88ApF//4kDAo//AgMQAgIFCjgFEjwFCOYIFFHQIFDn/+AoJ/BAoIqBAoN//xCBAoI5BDIPAgP//gFB8AFChYFBgf//EJAogOBAoSgBAoMHAQIFEFgXAAoJEBv4FCNoQFGVYd/wAFEYYIFIvwCBDoV8UwQCBcgUPwDwDfQMBaIYADA")) - }; - } - - // Default is always the HA icon - return { - width : 48, height : 48, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AD8BwAFDg/gAocP+AFDj4FEn/8Aod//wFD/1+FAf4j+8AoMD+EPDAUH+OPAoUP+fPAoUfBYk/C4l/EYIwC//8n//FwIFEgYFD4EH+E8nkP8BdBAonjjk44/wj/nzk58/4gAFDF4PgCIMHAoPwhkwh4FB/EEkEfIIWAHwIFC4A+BAoXgg4FDL4IFDL4IFDLIYFkAEQA==")) - }; -} - -// Try to read custom actions, otherwise use default -var triggers = [ - {display: "Not found.", trigger: "NOP", icon: "ha"}, -]; - -try{ - triggers = storage.read("ha.trigger.json"); - triggers = JSON.parse(triggers); -} catch(e) { - // In case there are no user triggers yet, we show the default... -} - - -function sendIntent(trigger){ - var retries=3; - - while(retries > 0){ - try{ - // Send a startup trigger such that we could also execute - // an action when the app is started :) - Bluetooth.println(JSON.stringify({ - t:"intent", - action:"com.espruino.gadgetbridge.banglejs.HA", - extra:{ - trigger: trigger - }}) - ); - retries = -1; - - } catch(e){ - retries--; - } - } -} +var triggers = ha.getTriggers(); function draw() { @@ -78,7 +16,7 @@ function draw() { var w = g.stringWidth(trigger.display); g.setFontAlign(-1,-1); - var icon = getIcon(trigger.icon); + var icon = trigger.getIcon(); g.setColor(g.theme.fg).drawImage(icon, 12, H/5-2); g.drawString("Home", icon.width + 20, H/5); g.drawString("Assistant", icon.width + 18, H/5+24); @@ -112,13 +50,11 @@ Bangle.on('touch', function(btn, e){ } if(!isRight && !isLeft){ - - // Send a default intent that we triggered something. - sendIntent("TRIGGER"); + ha.sendTrigger("TRIGGER"); // Now send the selected trigger Bangle.buzz(80, 0.6).then(()=>{ - sendIntent(triggers[position].trigger); + ha.sendTrigger(triggers[position].trigger); setTimeout(()=>{ Bangle.buzz(80, 0.6); }, 250); @@ -126,12 +62,14 @@ Bangle.on('touch', function(btn, e){ } }); + // Send intent that the we started the app. -sendIntent("APP_STARTED"); +ha.sendTrigger("APP_STARTED"); // Next load the widgets and draw the app Bangle.loadWidgets(); Bangle.drawWidgets(); +// Draw app draw(); setWatch(_=>load(), BTN1); diff --git a/apps/ha/ha.lib.js b/apps/ha/ha.lib.js new file mode 100644 index 000000000..b09cbeab2 --- /dev/null +++ b/apps/ha/ha.lib.js @@ -0,0 +1,80 @@ +/** + * This library can be used to read all triggers that a user + * configured and send a trigger to homeassistant. + */ +function _getIcon(trigger){ + icon = trigger.icon; + if(icon == "light"){ + return { + width : 48, height : 48, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AAMBwAFE4AFDgYFJjgFBnAFBjwXBvAFBh4jBuAFCAQPwAQMHAQPgEQQCBEgcf/AvDn/8Aof//5GDAoJOBh+BAoOB+EP8YFB4fwgfnAoPnGANHAoPjHYQFBHYQFd44pDg47C4/gh/DIIZNFLIplGgF//wFIgZ9BRIUHRII7Ch4FBUIUOAoKzCjwFEhgCBmDpIVooFFh4oCAA4LFC5b7BAob1BAYI=")) + }; + } else if(icon == "door"){ + return { + width : 48, height : 48, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AAM4Aok/4AED///Aov4Aon8DgQGBAv4FpnIFKJv4FweAQFFAgQFB8AFDnADC")) + }; + } else if (icon == "fire"){ + return { + width : 48, height : 48, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("ABsDAokBwAFE4AFE8AFE+AFE/AFJgf8Aon+AocHAokP/8QAokYAoUfAok//88ApF//4kDAo//AgMQAgIFCjgFEjwFCOYIFFHQIFDn/+AoJ/BAoIqBAoN//xCBAoI5BDIPAgP//gFB8AFChYFBgf//EJAogOBAoSgBAoMHAQIFEFgXAAoJEBv4FCNoQFGVYd/wAFEYYIFIvwCBDoV8UwQCBcgUPwDwDfQMBaIYADA")) + }; + } + + // Default is always the HA icon + return { + width : 48, height : 48, bpp : 1, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AD8BwAFDg/gAocP+AFDj4FEn/8Aod//wFD/1+FAf4j+8AoMD+EPDAUH+OPAoUP+fPAoUfBYk/C4l/EYIwC//8n//FwIFEgYFD4EH+E8nkP8BdBAonjjk44/wj/nzk58/4gAFDF4PgCIMHAoPwhkwh4FB/EEkEfIIWAHwIFC4A+BAoXgg4FDL4IFDL4IFDLIYFkAEQA==")) + }; +} + +exports.getTriggers = function(){ + var triggers = [ + {display: "Empty", trigger: "NOP", icon: "ha"}, + ]; + + try{ + triggers = require("Storage").read("ha.trigger.json"); + triggers = JSON.parse(triggers); + + // We lazy load all icons, otherwise, we have to keep + // all the icons n times in memory which can be + // problematic for embedded devices. Therefore, + // we lazy load icons only if needed using the getIcon + // method of each trigger... + triggers.forEach(trigger => { + trigger.getIcon = function(){ + return _getIcon(trigger); + } + }) + } catch(e) { + // In case there are no user triggers yet, we show the default... + } + + return triggers; +} + +exports.sendTrigger = function(triggerName){ + var retries=3; + + while(retries > 0){ + try{ + // Now lets send the trigger that we sould send. + Bluetooth.println(JSON.stringify({ + t:"intent", + action:"com.espruino.gadgetbridge.banglejs.HA", + extra:{ + trigger: triggerName + }}) + ); + retries = -1; + + } catch(e){ + retries--; + } + } +} \ No newline at end of file diff --git a/apps/ha/metadata.json b/apps/ha/metadata.json index 0f9929d8c..63308b933 100644 --- a/apps/ha/metadata.json +++ b/apps/ha/metadata.json @@ -1,7 +1,7 @@ { "id": "ha", "name": "HomeAssistant", - "version": "0.01", + "version": "0.02", "description": "Integrates your BangleJS into HomeAssistant.", "icon": "ha.png", "type": "app", @@ -19,6 +19,7 @@ ], "storage": [ {"name":"ha.app.js","url":"ha.app.js"}, + {"name":"ha.lib.js","url":"ha.lib.js"}, {"name":"ha.img","url":"ha.icon.js","evaluate":true} ] } diff --git a/apps/info/ChangeLog b/apps/info/ChangeLog index 07afedd21..400e7a119 100644 --- a/apps/info/ChangeLog +++ b/apps/info/ChangeLog @@ -1 +1,2 @@ -0.01: Release \ No newline at end of file +0.01: Release +0.02: Recfactoring and show weather data. \ No newline at end of file diff --git a/apps/info/info.app.js b/apps/info/info.app.js index c61a88045..9de80affc 100644 --- a/apps/info/info.app.js +++ b/apps/info/info.app.js @@ -1,27 +1,90 @@ -var s = require("Storage"); +const storage = require("Storage"); const locale = require('locale'); var ENV = process.env; var W = g.getWidth(), H = g.getHeight(); var screen = 0; -const maxScreen = 2; + + +var screens = [ + { + name: "General", + items: [ + {name: "Steps", fun: () => getSteps()}, + {name: "HRM", fun: () => getBpm()}, + {name: "", fun: () => ""}, + {name: "Temp.", fun: () => getWeatherTemp()}, + {name: "Humidity", fun: () => getWeatherHumidity()}, + {name: "Wind", fun: () => getWeatherWind()}, + ] + }, + { + name: "Hardware", + items: [ + {name: "Battery", fun: () => E.getBattery() + "%"}, + {name: "Charge?", fun: () => Bangle.isCharging() ? "Yes" : "No"}, + {name: "TempInt.", fun: () => locale.temp(parseInt(E.getTemperature()))}, + {name: "Bluetooth", fun: () => NRF.getSecurityStatus().connected ? "Conn" : "NoConn"}, + {name: "GPS", fun: () => Bangle.isGPSOn() ? "On" : "Off"}, + {name: "Compass", fun: () => Bangle.isCompassOn() ? "On" : "Off"}, + ] + }, + { + name: "Software", + items: [ + {name: "Firmw.", fun: () => ENV.VERSION}, + {name: "Boot.", fun: () => getVersion("boot.info")}, + {name: "Settings.", fun: () => getVersion("setting.info")}, + {name: "Storage.", fun: () => ""}, + {name: " Total", fun: () => ENV.STORAGE>>10}, + {name: " Free", fun: () => require("Storage").getFree()>>10}, + ] + } +]; + + +function getWeatherTemp(){ + try { + var weather = storage.readJSON('weather.json').weather; + return locale.temp(weather.temp-273.15); + } catch(ex) { } + + return "?"; +} + + +function getWeatherHumidity(){ + try { + var weather = storage.readJSON('weather.json').weather; + return weather.hum = weather.hum + "%"; + } catch(ex) { } + + return "?"; +} + + +function getWeatherWind(){ + try { + var weather = storage.readJSON('weather.json').weather; + var speed = locale.speed(weather.wind).replace("mph", ""); + return Math.round(speed * 1.609344) + "kph"; + } catch(ex) { } + + return "?"; +} + function getVersion(file) { - var j = s.readJSON(file,1); + var j = storage.readJSON(file,1); var v = ("object"==typeof j)?j.version:false; return v?((v?"v"+v:"Unknown")):"NO "; } -function drawData(name, value, y){ - g.drawString(name, 5, y); - g.drawString(value, 100, y); -} - function getSteps(){ try{ return Bangle.getHealthStatus("day").steps; } catch(e) { - return ">= 2v12"; + return ">2v12"; } } @@ -29,53 +92,36 @@ function getBpm(){ try{ return Math.round(Bangle.getHealthStatus("day").bpm) + "bpm"; } catch(e) { - return ">= 2v12"; + return ">2v12"; } } +function drawData(name, value, y){ + g.drawString(name, 10, y); + g.drawString(value, 100, y); +} + function drawInfo() { g.reset().clearRect(Bangle.appRect); var h=18, y = h;//-h; // Header - g.setFont("Vector", h+2).setFontAlign(0,-1); - g.drawString("--==|| INFO ||==--", W/2, 0); + g.drawLine(0,25,W,25); + g.drawLine(0,26,W,26); + + // Info body depending on screen g.setFont("Vector",h).setFontAlign(-1,-1); + screens[screen].items.forEach(function (item, index){ + drawData(item.name, item.fun(), y+=h); + }); - // Dynamic data - if(screen == 0){ - drawData("Steps", getSteps(), y+=h); - drawData("HRM", getBpm(), y+=h); - drawData("Battery", E.getBattery() + "%", y+=h); - drawData("Voltage", E.getAnalogVRef().toFixed(2) + "V", y+=h); - drawData("IntTemp.", locale.temp(parseInt(E.getTemperature())), y+=h); - } - - if(screen == 1){ - drawData("Charging?", Bangle.isCharging() ? "Yes" : "No", y+=h); - drawData("Bluetooth", NRF.getSecurityStatus().connected ? "Conn." : "Disconn.", y+=h); - drawData("GPS", Bangle.isGPSOn() ? "On" : "Off", y+=h); - drawData("Compass", Bangle.isCompassOn() ? "On" : "Off", y+=h); - drawData("HRM", Bangle.isHRMOn() ? "On" : "Off", y+=h); - } - - // Static data - if(screen == 2){ - drawData("Firmw.", ENV.VERSION, y+=h); - drawData("Boot.", getVersion("boot.info"), y+=h); - drawData("Settings", getVersion("setting.info"), y+=h); - drawData("Storage", "", y+=h); - drawData(" Total", ENV.STORAGE>>10, y+=h); - drawData(" Free", require("Storage").getFree()>>10, y+=h); - } - - if(Bangle.isLocked()){ - g.setFont("Vector",h-2).setFontAlign(-1,-1); - g.drawString("Locked", 0, H-h+2); - } - + // Bottom + g.drawLine(0,H-h-3,W,H-h-3); + g.drawLine(0,H-h-2,W,H-h-2); + g.setFont("Vector",h-2).setFontAlign(-1,-1); + g.drawString(screens[screen].name, 2, H-h+2); g.setFont("Vector",h-2).setFontAlign(1,-1); - g.drawString((screen+1) + "/3", W, H-h+2); + g.drawString((screen+1) + "/" + screens.length, W, H-h+2); } drawInfo(); @@ -88,14 +134,15 @@ Bangle.on('touch', function(btn, e){ var isRight = e.x > right; if(isRight){ - screen = (screen + 1) % (maxScreen+1); + screen = (screen + 1) % screens.length; } if(isLeft){ screen -= 1; - screen = screen < 0 ? maxScreen : screen; + screen = screen < 0 ? screens.length-1 : screen; } + Bangle.buzz(40, 0.6); drawInfo(); }); @@ -104,5 +151,4 @@ Bangle.on('lock', function(isLocked) { }); Bangle.loadWidgets(); -for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} -// Bangle.drawWidgets(); \ No newline at end of file +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/info/metadata.json b/apps/info/metadata.json index f05f0e134..97aeb687a 100644 --- a/apps/info/metadata.json +++ b/apps/info/metadata.json @@ -1,7 +1,7 @@ { "id": "info", "name": "Info", - "version": "0.01", + "version": "0.02", "description": "An application that displays information such as battery level, steps etc.", "icon": "info.png", "type": "app", diff --git a/apps/info/screenshot_1.png b/apps/info/screenshot_1.png index 97d42a896..25f5b0a8b 100644 Binary files a/apps/info/screenshot_1.png and b/apps/info/screenshot_1.png differ diff --git a/apps/info/screenshot_2.png b/apps/info/screenshot_2.png index 2d25dd4e6..517a83299 100644 Binary files a/apps/info/screenshot_2.png and b/apps/info/screenshot_2.png differ diff --git a/apps/info/screenshot_3.png b/apps/info/screenshot_3.png index 782e4a195..6802495f5 100644 Binary files a/apps/info/screenshot_3.png and b/apps/info/screenshot_3.png differ