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 000000000..fc5448876 Binary files /dev/null and b/apps/gbridge/app.png differ 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); +}}; + +})();