From bcf0f80d294626c40c07d1251b09c2fe2522c7ab Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 5 Dec 2019 14:48:36 +0000 Subject: [PATCH] add gadgetbridge app, plus ad versions --- apps.json | 82 +++++++++++++++++++++++---- apps/gbridge/app-icon.js | 1 + apps/gbridge/app.js | 19 +++++++ apps/gbridge/app.json | 5 ++ apps/gbridge/app.png | Bin 0 -> 2588 bytes apps/gbridge/widget.js | 118 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+), 12 deletions(-) create mode 100644 apps/gbridge/app-icon.js create mode 100644 apps/gbridge/app.js create mode 100644 apps/gbridge/app.json create mode 100644 apps/gbridge/app.png create mode 100644 apps/gbridge/widget.js diff --git a/apps.json b/apps.json index dfadf9c5d..3749f4e07 100644 --- a/apps.json +++ b/apps.json @@ -1,18 +1,8 @@ [ - { "id": "clck3x2", - "name": "3x2 Pixel Clock", - "icon": "clock3x2.png", - "description": "This is a simple clock using minimalistic 3x2 pixel numerical digits", - "tags": "clock", - "storage": [ - {"name":"+clck3x2","url":"clock3x2.json"}, - {"name":"-clck3x2","url":"clock3x2.js"}, - {"name":"*clck3x2","url":"clock3x2-icon.js","evaluate":true} - ] - }, { "id": "boot", "name": "Bootloader", "icon": "bootloader.png", + "version":"0.01", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "tags": "tool,system", "storage": [ @@ -20,9 +10,23 @@ ], "sortorder" : -10 }, + { "id": "gbridge", + "name": "Gadgetbridge", + "icon": "app.png", + "version":"0.01", + "description": "The default notification handler for Gadgetbridge notifications from Android", + "tags": "tool,system,android", + "storage": [ + {"name":"+gbridge","url":"app.json"}, + {"name":"-gbridge","url":"app.js"}, + {"name":"*gbridge","url":"app-icon.js","evaluate":true}, + {"name":"=gbridge","url":"widget.js"} + ] + }, { "id": "mclock", "name": "Morphing Clock", "icon": "clock-morphing.png", + "version":"0.01", "description": "7 segment clock that morphs between minutes and hours", "tags": "clock", "type":"clock", @@ -37,6 +41,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", + "version":"0.01", "description": "A menu for setting up Bangle.js - by default this disables Bluetooth unless you enable 'BLE' AND 'Dev'", "tags": "tool,system", "storage": [ @@ -51,6 +56,7 @@ { "id": "wclock", "name": "Word Clock", "icon": "clock-word.png", + "version":"0.01", "description": "Display Time as Text", "tags": "clock", "type":"clock", @@ -64,6 +70,7 @@ { "id": "aclock", "name": "Analog Clock", "icon": "clock-analog.png", + "version":"0.01", "description": "An Analog Clock", "tags": "clock", "type":"clock", @@ -74,9 +81,22 @@ {"name":"*aclock","url":"clock-analog-icon.js","evaluate":true} ] }, + { "id": "clck3x2", + "name": "3x2 Pixel Clock", + "icon": "clock3x2.png", + "version":"0.01", + "description": "This is a simple clock using minimalistic 3x2 pixel numerical digits", + "tags": "clock", + "storage": [ + {"name":"+clck3x2","url":"clock3x2.json"}, + {"name":"-clck3x2","url":"clock3x2.js"}, + {"name":"*clck3x2","url":"clock3x2-icon.js","evaluate":true} + ] + }, { "id": "trex", "name": "T-Rex", "icon": "trex.png", + "version":"0.01", "description": "T-Rex game in the style of Chrome's offline game", "tags": "game", "allow_emulator":true, @@ -89,6 +109,7 @@ { "id": "astroid", "name": "Asteroids!", "icon": "asteroids.png", + "version":"0.01", "description": "Retro asteroids game", "tags": "game", "allow_emulator":true, @@ -101,6 +122,7 @@ { "id": "clickms", "name": "Click Master", "icon": "click-master.png", + "version":"0.01", "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", "tags": "game", "storage": [ @@ -112,6 +134,7 @@ { "id": "horsey", "name": "Horse Race!", "icon": "horse-race.png", + "version":"0.01", "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", "tags": "game", "storage": [ @@ -123,6 +146,7 @@ { "id": "compass", "name": "Compass", "icon": "compass.png", + "version":"0.01", "description": "Simple compass that points North", "tags": "tool,outdoors", "storage": [ @@ -134,6 +158,7 @@ { "id": "gpstime", "name": "GPS Time", "icon": "gpstime.png", + "version":"0.01", "description": "Update the Bangle.js's clock based on the time from the GPS receiver", "tags": "tool", "storage": [ @@ -145,6 +170,7 @@ { "id": "openloc", "name": "Open Location / Plus Codes", "icon": "openlocation.png", + "version":"0.01", "description": "Convert your current GPS location to a series of characters", "tags": "tool,outdoors", "storage": [ @@ -155,6 +181,7 @@ { "id": "speedo", "name": "Speedo", "icon": "speedo.png", + "version":"0.01", "description": "Show the current speed according to the GPS", "tags": "tool,outdoors", "storage": [ @@ -166,6 +193,7 @@ { "id": "slevel", "name": "Spirit Level", "icon": "spiritlevel.png", + "version":"0.01", "description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat", "tags": "tool", "storage": [ @@ -177,6 +205,7 @@ { "id": "files", "name": "App Manager", "icon": "files.png", + "version":"0.01", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "tags": "tool,system", "storage": [ @@ -188,6 +217,7 @@ { "id": "sbat", "name": "Battery Level Widget", "icon": "widget-battery.png", + "version":"0.01", "description": "Show the current battery level and charging status in the top right of the clock", "tags": "widget,battery", "type":"widget", @@ -199,6 +229,7 @@ { "id": "sbt", "name": "Bluetooth Widget", "icon": "widget-bluetooth.png", + "version":"0.01", "description": "Show the current Bluetooth connection status in the top right of the clock", "tags": "widget,bluetooth", "type":"widget", @@ -210,6 +241,7 @@ { "id": "hrm", "name": "Heart Rate Monitor", "icon": "heartrate.png", + "version":"0.01", "description": "Measure your current heart rate", "tags": "health", "storage": [ @@ -221,6 +253,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", + "version":"0.01", "description": "Simple stopwatch with Lap Time recording", "tags": "health", "allow_emulator":true, @@ -233,6 +266,7 @@ { "id": "hidmsic", "name": "Bluetooth Music Controls", "icon": "hid-music.png", + "version":"0.01", "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", "tags": "bluetooth", "storage": [ @@ -244,6 +278,7 @@ { "id": "hidkbd", "name": "Bluetooth Keyboard", "icon": "hid-keyboard.png", + "version":"0.01", "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", "tags": "bluetooth", "storage": [ @@ -255,6 +290,7 @@ { "id": "hidbkbd", "name": "Binary Bluetooth Keyboard", "icon": "hid-binary-keyboard.png", + "version":"0.01", "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", "tags": "bluetooth", "storage": [ @@ -266,6 +302,7 @@ { "id": "animals", "name": "Animals Game", "icon": "animals.png", + "version":"0.01", "description": "Simple toddler's game - displays a different number of animals each time the screen is pressed", "tags": "game", "storage": [ @@ -286,6 +323,7 @@ { "id": "qrcode", "name": "Custom QR Code", "icon": "qrcode.png", + "version":"0.01", "description": "Use this to upload a customised QR code to Bangle.js", "tags": "", "custom": "qrcode.html", @@ -298,6 +336,7 @@ { "id": "beer", "name": "Beer Compass", "icon": "beercompass.png", + "version":"0.01", "description": "Uploads all the pubs in an area onto your watch, so it can always point you at the nearest one", "tags": "", "custom": "beercompass.html", @@ -310,6 +349,7 @@ { "id": "route", "name": "Route Viewer", "icon": "route.png", + "version":"0.01", "description": "Upload a KML file of a route, and have your watch display a map with how far around it you are", "tags": "", "custom": "route.html", @@ -319,11 +359,11 @@ {"name":"=route"} ] }, - { "id": "start", "name": "NCEU Startup", "icon": "start.png", + "version":"0.01", "description": "NodeConfEU 2019 Startup Sequence", "tags": "start", "storage": [ @@ -341,6 +381,7 @@ { "id": "funrun5", "name": "NCEU 5K Fun Run", "icon": "nceu-funrun.png", + "version":"0.01", "description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it", "tags": "health", "storage": [ @@ -353,6 +394,7 @@ { "id": "nceuwid", "name": "NCEU Logo Widget", "icon": "nceu-widget.png", + "version":"0.01", "description": "Show the NodeConf EU logo in the top left", "tags": "widget", "type":"widget", @@ -365,6 +407,7 @@ { "id": "sclock", "name": "Simple Clock", "icon": "clock-simple.png", + "version":"0.01", "description": "Simple Digital Clock", "tags": "sclock", "type":"clock", @@ -378,6 +421,7 @@ { "id": "gesture", "name": "Gesture Test", "icon": "gesture.png", + "version":"0.01", "description": "BETA! Uploads a basic Tensorflow Gesture model, and then outputs each gesture as a message", "tags": "gesture,ai", "type":"app", @@ -392,6 +436,7 @@ { "id": "pparrot", "name": "Party Parrot", "icon": "party-parrot.png", + "version":"0.01", "description": "Party with a parrot on your wrist", "tags": "party,parrot,lol", "type":"app", @@ -405,6 +450,7 @@ { "id": "hrings", "name": "Hypno Rings", "icon": "hypno-rings.png", + "version":"0.01", "description": "Experiment with trippy rings, press buttons for change", "tags": "rings,hypnosis,psychadelic", "type":"app", @@ -418,6 +464,7 @@ { "id": "morse", "name": "Morse Code", "icon": "morse-code.png", + "version":"0.01", "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", "tags": "morse,sound,visual,input", "type":"app", @@ -431,6 +478,7 @@ "id": "blescan", "name": "BLE Scanner", "icon": "blescan.png", + "version":"0.01", "description": "Scan for advertising BLE devices", "tags" : "bluetooth", "storage" : [ @@ -442,6 +490,7 @@ { "id": "mmonday", "name": "Manic Monday Tone", "icon": "manic-monday-icon.png", + "version":"0.01", "description": "The Bangles make a comeback", "tags": "sound", "storage": [ @@ -453,6 +502,7 @@ { "id": "jbells", "name": "Jingle Bells", "icon": "jbells.png", + "version":"0.01", "description": "Play Jingle Bells", "tags": "sound", "type":"app", @@ -465,6 +515,7 @@ { "id": "scolor", "name": "Show Color", "icon": "show-color.png", + "version":"0.01", "description": "Display all available Colors and Names", "tags": "tool", "type":"app", @@ -478,6 +529,7 @@ { "id": "miclock", "name": "Mixed Clock", "icon": "clock-mixed.png", + "version":"0.01", "description": "A mix of analog and digital Clock", "tags": "clock", "type":"clock", @@ -491,6 +543,7 @@ { "id": "bclock", "name": "Binary Clock", "icon": "clock-binary.png", + "version":"0.01", "description": "A simple binary clock watch face", "tags": "clock", "type":"clock", @@ -504,6 +557,7 @@ { "id": "clotris", "name": "Clock-Tris", "icon": "clock-tris.png", + "version":"0.01", "description": "A fully functional clone of a classic game of falling blocks", "tags": "game", "allow_emulator":true, @@ -517,6 +571,7 @@ { "id": "flappy", "name": "Flappy Bird", "icon": "app.png", + "version":"0.01", "description": "A Flappy Bird game clone", "tags": "game", "allow_emulator":true, @@ -530,6 +585,7 @@ "id": "gpsinfo", "name": "GPS Info", "icon": "gps-info.png", + "version":"0.01", "description": "An application that displays information about altitude, lat/lon, satellites and time", "tags": "gps", "type": "app", @@ -543,6 +599,7 @@ "id": "pomodo", "name":"Pomodoro", "icon":"pomodoro.png", + "version":"0.01", "description": "A simple pomodoro timer.", "tags": "pomodoro,cooking,tools", "type": "app", @@ -556,6 +613,7 @@ { "id": "blobclk", "name": "Large Digit Clock", "icon": "clock-blob.png", + "version":"0.01", "description": "A clock with big digits", "tags": "clock", "type":"clock", diff --git a/apps/gbridge/app-icon.js b/apps/gbridge/app-icon.js new file mode 100644 index 000000000..7840d9b6f --- /dev/null +++ b/apps/gbridge/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwg96xAACCqMICwYABwAsSAAoWWDBhEGJSAWLGBQuMGBQWNGBAuH/84GBoNGx///AwMFxH/mQYHGAgXHn//GIIXLIo84nAxBwZIKFo4YBMAM/PQwXJCwIABn8y//zC5BeFwYXDmaSCGApgCC4oRBAAQ0CwYwFC5BeB/GCkY0B+YHBC452H+YqBSYRgJUw7tCAYIZCC6ApBU4TZHC44rCJAJgCR4wXLIgMzC4MzF55ICSYUzC6bZDPgIXOJAYACLwwXCa4oXHBgzvIJAzVGC7ZgHwXdAAXSLxAXIpvUkUilvdC6Pd7ADBwndlAXJMAwXLLwYXI6Wq1RHBC5RIGCYIAC6hGJGA6nKFwp5IABAWGbRDUKGCYWIGBouJGBoWKDBYWMJRBELGRQVRAE4A==")) diff --git a/apps/gbridge/app.js b/apps/gbridge/app.js new file mode 100644 index 000000000..06fe3ce9f --- /dev/null +++ b/apps/gbridge/app.js @@ -0,0 +1,19 @@ +function gb(j) { + Bluetooth.println(JSON.stringify(j)); +} + +var mainmenu = { + "" : { "title" : "Gadgetbridge" }, + "Connected" : { value : NRF.getSecurityStatus().connected }, + "Find Phone" : function() { E.showMenu(findPhone); }, + "Exit" : load, +}; + +var findPhone = { + "" : { "title" : "-- Find Phone --" }, + "On" : _=>gb({t:"findPhone",n:true}), + "Off" : _=>gb({t:"findPhone",n:false}), + "< Back" : function() { E.showMenu(mainmenu); }, +}; + +E.showMenu(mainmenu); diff --git a/apps/gbridge/app.json b/apps/gbridge/app.json new file mode 100644 index 000000000..f5c8f3991 --- /dev/null +++ b/apps/gbridge/app.json @@ -0,0 +1,5 @@ +{ + "name":"Gadgetbridge", + "icon":"*gbridge", + "src":"-gbridge" +} diff --git a/apps/gbridge/app.png b/apps/gbridge/app.png new file mode 100644 index 0000000000000000000000000000000000000000..fc544887622c08e39f2eba5f2afb7bd953e4ba7a GIT binary patch literal 2588 zcmYjTc{tQ<7yensRzj8}%Zy#&N3XRe%NSWhLn-?hGiEYoyt6Q5&n{~rgm=(FDA~8j zk_eFsS>J3GUQ0?bcF1;z%qNLm>pv2xJmqi>8w>cq|1G7s1v~- z3uqgFTKeE=Ep7ey)*Ij17~2DkBbiRYU;#Xh7C=1%g1!VAp6;!QA^U?=44F>DYWNT^ zcvTe=>=B&|Z*8z+g#KEEV())}W$69ZfB;%gGx80DQ_; zNK+?#)LNb&QEW`SHzMf8*Au*WyWO1nuAwLfF zE+(d2fa9%o!g$mpbr(2 zL|NV8%cghQj5&1I<}*GBco}N-d>lO{yxR3>740A5SSltj>M-rX*P3JsKZBa*+5oN( zk9WH4={^#26@5};DC_%{C%qjI!MwX7*%(=guNtf<7$$#*edVlg2orZVj{N3Oopeey z1OnpT<>nIYOtMO(VY85r>+!jeZBFr4A7d#}@zKDtYrT{hR^;n6xCv)Kf>iI*08xvb z$jv2Vpt$0+Ws=Bth+Z926r z!(+qq{{1lc`RiU%;DrY5E)q@DyzHWramMqE<$nCim}HK$4Z2wnNK?N0beZ#n>?`bY zCoMH=(lWVP3Pn+xlrdyNEd7-vLh@@3o;M$lT7+rXVdtY0Ss|uIEw86|ynfAAW#k|2 z74l8v^7`G4^iZcolaxx4hfxt{Y5_i1gE-7Dv(3`(I8CJ*>aDW2i9TisZ#;Nr{O2zw zaeQj=W82rk)xrmv4_$;|v7Rx9`59dqg17VBRf2AI+CP{GZEtH{s97TI!p(e){J-44 zH#zu~7yLRjdQY+ExKdAvRrWuXzJ9^5NByT6^rR!rV-=qXPIW#0Ba`r_5!)##X-h)(S#u+bgv}A+E{;RosCJq#S6vdw_f|rhtYk-eRPv*5hGF{SKF@4W$R$bg|amBFKx?Zz)WjNG)iMG6% zWZ|b)L6qEu$h4IJj>OB{mR|GiAvb1RFK0tK6oS<%rXn)to!7T+1c8o5Y6VTfYQU$X z9tNQ)Pwyg0fz5(jH{^AMXmvN`5ptrokyuvU$Y2xHgP{ns-PZCzoEsS-} zQP0ip%OvEw`LFo?JnKBHsAF)~l3V7NRLYK9)I!+b3sHrEmbSe+u;UWVVa{FWWiCSi z)?!?~eKZ68dD|Ag>+s0o4r$(AyeIU-)T`~g+~M%E$r^IHvC3&$naxXj$RBHJrD-ea zKwrCph!=wida;7zHK;&e1~sBSk=Vq zix^b$cW9TmjzZ6Q$bNUolvK-5ZJq*nn<>=NJ}L}DhW!Po8Fw<6*|4ZVU(PmR0bX$C z-mA)dmGxJ49szV4TJULyj=TYhgsDUEk6Ri;$J`vh@0@Ud-?xXv)4ANDIt2H^y{;*8 z3hY&h*6isf?8Fqf4qxW;en#IyaF|aRhidFE`MXXUIJIT)4V~TJ>}y~&j^dY6AK6o^ z2fnow^}B~JRLb+{qxh7?+w9GzkbVmglGwdSdTayF*teaI58KM+E<5s9u$N5gCzmh1 zN3MTNeaU~vvAk&c;x9>r_0zUBopj$=xT^Phz?N{u(G}tg1AL04Y&5xSTK;`Rhd{8{ zF$7Vz2{*@l$Nsg;T^qcmi}KGG<;}HttW_>O+;wl?J6?O*(Rguhy5xl`6g0_jEmLnc zdPCX}9H`INdpqu;zA93 zgm*PZx0U1`27$ktzgf)zxX!Xkj(?u*Da~^AzZscn)#U&#rFzG}O&YB=?p5c%foEhm z-{uj!7wx&^sb%(xl}fyDo-1#~&r(m@r9hbTMd^ur%1Utfp+I``)h(|cuC9xts7SHL zk!~VeTw_zi(|TS?w%4KEMq<^8{hg8U{e2Owgtb&@S{Ni@QIfgXUf2r>lX?EqCI%H> zylU~p*XR1iPkzZ%{q^xb)xMf!7bkd^N+#b{YrHP*7B;O~EQ90{pg-J=cd`qIM(F-H c>Z$Xa7a!Gv7?TP#X3sf*mAM_V3gH#~FCw3!%>V!Z literal 0 HcmV?d00001 diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js new file mode 100644 index 000000000..21545c5f0 --- /dev/null +++ b/apps/gbridge/widget.js @@ -0,0 +1,118 @@ +(function() { + var musicState = "stop"; + var musicInfo = {"artist":"","album":"","track":""}; + var scrollPos = 0; + function gb(j) { + Bluetooth.println(JSON.stringify(j)); + } + function show(size,render) { + var oldMode = Bangle.getLCDMode(); + Bangle.setLCDMode("direct"); + g.setClipRect(0,240,239,319); + g.setColor("#404040"); + g.fillRect(1,241,238,318); + render(320-size); + g.setColor("#ffffff"); + g.fillRect(0,240,1,319); + g.fillRect(238,240,239,319); + g.fillRect(2,318,238,319); + Bangle.setLCDPower(1); // light up + Bangle.setLCDMode(oldMode); // clears cliprect + function anim() { + scrollPos-=2; + if (scrollPos<-size) scrollPos=-size; + Bangle.setLCDOffset(scrollPos); + if (scrollPos>-size) setTimeout(anim,10); + } + anim(); + } + function hide() { + function anim() { + scrollPos+=4; + if (scrollPos>0) scrollPos=0; + Bangle.setLCDOffset(scrollPos); + if (scrollPos<0) setTimeout(anim,10); + } + anim(); + } + + Bangle.on('touch',function() { + if (scrollPos) hide(); + }); + Bangle.on('swipe',function(dir) { + if (musicState=="play") { + gb({t:"music",n:dir>0?"next":"previous"}); + } + }); + gb({t:"status",bat:E.getBattery()}); + + global.GB = function(j) { + switch (j.t) { + case "notify": + show(80,function(y) { + // TODO: icon based on src? + var x = 120; + g.setFontAlign(0,0); + g.setFont("6x8",1); + g.setColor("#40d040"); + g.drawString(j.src,x,y+7); + g.setColor("#ffffff"); + g.setFont("6x8",2); + g.drawString(j.title,x,y+25); + g.setFont("6x8",1); + g.setColor("#b0b0b0"); + // split text up a word boundaries + var txt = j.body.split("\n"); + var MAXCHARS = 38; + for (var i=0;iMAXCHARS) { + var p = MAXCHARS; + while (p>MAXCHARS-8 && !" \t-_".includes(l[p])) + p--; + if (p==MAXCHARS-8) p=MAXCHARS; + txt[i] = l.substr(0,p); + txt.splice(i+1,0,l.substr(p)); + } + } + g.setFontAlign(-1,-1); + g.drawString(txt.join("\n"),10,y+40); + Bangle.buzz(); + }); + break; + case "musicinfo": + musicInfo = j; + break; + case "musicstate": + musicState = j.state; + if (musicState=="play") + show(40,function(y) { + g.setColor("#ffffff"); + g.drawImage( require("heatshrink").decompress(atob("jEYwILI/EAv/8gP/ARcMgOAASN8h+A/kfwP8n4CD/E/gHgjg/HA=")),8,y+8); + g.setFontAlign(-1,-1); + g.setFont("6x8",1); + var x = 40; + g.setFont("4x6",2); + g.setColor("#ffffff"); + g.drawString(musicInfo.artist,x,y+8); + g.setFont("6x8",1); + g.setColor("#c0c0c0"); + g.drawString(musicInfo.track,x,y+22); + }); + if (musicState=="pause") + hide(); + break; + } + }; + + + +var xpos = WIDGETPOS.tl; +WIDGETPOS.tl+=24; +WIDGETS["gbridgew"]={draw:function() { + g.drawImage(require("heatshrink").decompress(atob("i0WwgHExAABCIwJCBYwJEBYkIBQ2ACgvzCwoECx/z/AKDD4WD+YLBEIYKCx//+cvnAKCBwU/mc4/8/HYv//Ev+Y4EEAePn43DBQkzn4rCEIoABBIwKHO4cjmczK42I6mqlqEEBQeIBQaDED4IgDUhi6KaBbmIA==")),xpos+1,1); + g.setColor(1,1,1); +}}; + +})();