diff --git a/apps/_example_clkinfo/ChangeLog b/apps/_example_clkinfo/ChangeLog index 4c21f3ace..78ba28f3b 100644 --- a/apps/_example_clkinfo/ChangeLog +++ b/apps/_example_clkinfo/ChangeLog @@ -1 +1 @@ -0.01: New Widget! +0.01: New Clock Info! diff --git a/apps/_example_clock/ChangeLog b/apps/_example_clock/ChangeLog new file mode 100644 index 000000000..09953593e --- /dev/null +++ b/apps/_example_clock/ChangeLog @@ -0,0 +1 @@ +0.01: New Clock! diff --git a/apps/_example_clock/README.md b/apps/_example_clock/README.md new file mode 100644 index 000000000..5d750a965 --- /dev/null +++ b/apps/_example_clock/README.md @@ -0,0 +1,25 @@ +# Clock Name + +More info on making Clock Faces: https://www.espruino.com/Bangle.js+Clock + +Describe the Clock... + +## Usage + +Describe how to use it + +## Features + +Name the function + +## Controls + +Name the buttons and what they are used for + +## Requests + +Name who should be contacted for support/update requests + +## Creator + +Your name diff --git a/apps/_example_clock/app-icon.js b/apps/_example_clock/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/_example_clock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/_example_clock/clock.js b/apps/_example_clock/clock.js new file mode 100644 index 000000000..7e97cf758 --- /dev/null +++ b/apps/_example_clock/clock.js @@ -0,0 +1,44 @@ +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function draw() { + // queue next draw in one minute + queueDraw(); + // Work out where to draw... + var x = g.getWidth()/2; + var y = g.getHeight()/2; + g.reset(); + // work out locale-friendly date/time + var date = new Date(); + var timeStr = require("locale").time(date,1); + var dateStr = require("locale").date(date); + // draw time + g.setFontAlign(0,0).setFont("Vector",48); + g.clearRect(0,y-15,g.getWidth(),y+25); // clear the background + g.drawString(timeStr,x,y); + // draw date + y += 35; + g.setFontAlign(0,0).setFont("6x8"); + g.clearRect(0,y-4,g.getWidth(),y+4); // clear the background + g.drawString(dateStr,x,y); +} + +// Clear the screen once, at startup +g.clear(); +// draw immediately at first, queue update +draw(); + +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/_example_clock/icon.png b/apps/_example_clock/icon.png new file mode 100644 index 000000000..582cb2e08 Binary files /dev/null and b/apps/_example_clock/icon.png differ diff --git a/apps/_example_clock/metadata.json b/apps/_example_clock/metadata.json new file mode 100644 index 000000000..c6e1256d3 --- /dev/null +++ b/apps/_example_clock/metadata.json @@ -0,0 +1,15 @@ +{ "id": "7chname", + "name": "My clock human readable name", + "shortName":"Short Name", + "version":"0.01", + "description": "A detailed description of my clock", + "icon": "icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"7chname.app.js","url":"app.js"}, + {"name":"7chname.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index d531e43a9..108242825 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -32,3 +32,4 @@ Allow alarm enable/disable 0.31: Implement API for activity fetching 0.32: Added support for loyalty cards from gadgetbridge +0.33: Fix alarms created in Gadgetbridge not repeating diff --git a/apps/android/boot.js b/apps/android/boot.js index 846fc40a8..63f9b2883 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -81,7 +81,12 @@ for (var j = 0; j < event.d.length; j++) { // prevents all alarms from going off at once?? var dow = event.d[j].rep; - if (!dow) dow = 127; //if no DOW selected, set alarm to all DOW + var rp = false; + if (!dow) { + dow = 127; //if no DOW selected, set alarm to all DOW + } else { + rp = true; + } var last = (event.d[j].h * 3600000 + event.d[j].m * 60000 < currentTime) ? (new Date()).getDate() : 0; var a = require("sched").newDefaultAlarm(); a.id = "gb"+j; @@ -89,6 +94,7 @@ a.on = event.d[j].on !== undefined ? event.d[j].on : true; a.t = event.d[j].h * 3600000 + event.d[j].m * 60000; a.dow = ((dow&63)<<1) | (dow>>6); // Gadgetbridge sends DOW in a different format + a.rp = rp; a.last = last; alarms.push(a); } diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 68bd946c5..5babc520b 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.32", + "version": "0.33", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", diff --git a/apps/aviatorclk/ChangeLog b/apps/aviatorclk/ChangeLog index 971e5b97e..929ee8387 100644 --- a/apps/aviatorclk/ChangeLog +++ b/apps/aviatorclk/ChangeLog @@ -1 +1,2 @@ 1.00: initial release +1.01: added tap event to scroll METAR and toggle seconds display diff --git a/apps/aviatorclk/README.md b/apps/aviatorclk/README.md index fe7376b5d..ac27b80d3 100644 --- a/apps/aviatorclk/README.md +++ b/apps/aviatorclk/README.md @@ -18,15 +18,20 @@ module after installing this app. - Latest METAR for the nearest airport (scrollable) Tap the screen in the top or bottom half to scroll the METAR text (in case not -the whole report fits on the screen). +the whole report fits on the screen). You can also tap the watch from the top +or bottom to scroll, which works even with the screen locked. The colour of the METAR text will change to orange if the report is more than 1h old, and red if it's older than 1.5h. +To toggle the seconds display, double tap the watch from either the left or +right. This only changes the display "temporarily" (ie. it doesn't change the +default configured through the settings). + ## Settings -- **Show Seconds**: to conserve battery power, you can turn the seconds display off +- **Show Seconds**: to conserve battery power, you can turn the seconds display off (as the default) - **Invert Scrolling**: swaps the METAR scrolling direction of the top and bottom taps diff --git a/apps/aviatorclk/aviatorclk.app.js b/apps/aviatorclk/aviatorclk.app.js index 1d99fdbde..33d671bc7 100644 --- a/apps/aviatorclk/aviatorclk.app.js +++ b/apps/aviatorclk/aviatorclk.app.js @@ -169,6 +169,7 @@ function drawSeconds() { let seconds = now.getSeconds().toString(); if (seconds.length == 1) seconds = '0' + seconds; let y = Bangle.appRect.y + mainTimeHeight - 3; + g.setBgColor(g.theme.bg); g.setFontAlign(-1, 1).setFont("Vector", secondaryFontHeight).setColor(COLOUR_GREY); g.drawString(seconds, horizontalCenter + 54, y, true); } @@ -232,10 +233,10 @@ function draw() { // initialise g.clear(true); -// scroll METAR lines on taps -Bangle.setUI("clockupdown", action => { +// scroll METAR lines (either by touch or tap) +function scrollAVWX(action) { switch (action) { - case -1: // top tap + case -1: // top touch/tap if (settings.invertScrolling) { if (METARscollLines > 0) METARscollLines--; @@ -244,7 +245,7 @@ Bangle.setUI("clockupdown", action => { METARscollLines++; } break; - case 1: // bottom tap + case 1: // bottom touch/tap if (settings.invertScrolling) { if (METARscollLines < METARlinesCount - 4) METARscollLines++; @@ -254,11 +255,41 @@ Bangle.setUI("clockupdown", action => { } break; default: - // ignore + // ignore other actions } drawAVWX(); +} + +Bangle.on('tap', data => { + switch (data.dir) { + case 'top': + scrollAVWX(-1); + break; + case 'bottom': + scrollAVWX(1); + break; + case 'left': + case 'right': + // toggle seconds display on double taps left or right + if (data.double) { + if (settings.showSeconds) { + clearInterval(secondsInterval); + let y = Bangle.appRect.y + mainTimeHeight - 3; + g.clearRect(horizontalCenter + 54, y - secondaryFontHeight, g.getWidth(), y); + settings.showSeconds = false; + } else { + settings.showSeconds = true; + syncSecondsUpdate(); + } + } + break; + default: + // ignore other taps + } }); +Bangle.setUI("clockupdown", scrollAVWX); + // load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -276,8 +307,8 @@ updateAVWX(); // TMP for debugging: -//METAR = 'YAAA 011100Z 21014KT CAVOK 23/08 Q1018 RMK RF000/0000'; -//METAR = 'YAAA 150900Z 14012KT 9999 SCT045 BKN064 26/14 Q1012 RMK RF000/0000 DL-W/DL-NW'; -//METAR = 'YAAA 020030Z VRB CAVOK'; +//METAR = 'YAAA 011100Z 21014KT CAVOK 23/08 Q1018 RMK RF000/0000'; drawAVWX(); +//METAR = 'YAAA 150900Z 14012KT 9999 SCT045 BKN064 26/14 Q1012 RMK RF000/0000 DL-W/DL-NW'; drawAVWX(); +//METAR = 'YAAA 020030Z VRB CAVOK'; drawAVWX(); //METARts = new Date(Date.now() - 61 * 60000); // 61 to trigger warning, 91 to trigger alert diff --git a/apps/aviatorclk/aviatorclk.settings.js b/apps/aviatorclk/aviatorclk.settings.js index 6db212ef1..d3ffbaad2 100644 --- a/apps/aviatorclk/aviatorclk.settings.js +++ b/apps/aviatorclk/aviatorclk.settings.js @@ -17,7 +17,6 @@ "< Back" : () => back(), 'Show Seconds': { value: !!settings.showSeconds, // !! converts undefined to false - format: v => v ? "On" : "Off", onchange: v => { settings.showSeconds = v; writeSettings(); @@ -25,7 +24,6 @@ }, 'Invert Scrolling': { value: !!settings.invertScrolling, // !! converts undefined to false - format: v => v ? "On" : "Off", onchange: v => { settings.invertScrolling = v; writeSettings(); diff --git a/apps/aviatorclk/metadata.json b/apps/aviatorclk/metadata.json index 6ae8c4a18..9d2b0beef 100644 --- a/apps/aviatorclk/metadata.json +++ b/apps/aviatorclk/metadata.json @@ -2,7 +2,7 @@ "id": "aviatorclk", "name": "Aviator Clock", "shortName":"AV8R Clock", - "version":"1.00", + "version":"1.01", "description": "A clock for aviators, with local time and UTC - and the latest METAR for the nearest airport", "icon": "aviatorclk.png", "screenshots": [{ "url": "screenshot.png" }, { "url": "screenshot2.png" }], diff --git a/apps/bthome/ChangeLog b/apps/bthome/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/bthome/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/bthome/README.md b/apps/bthome/README.md new file mode 100644 index 000000000..d232e8d64 --- /dev/null +++ b/apps/bthome/README.md @@ -0,0 +1,26 @@ +# BTHome + +This uses BTHome (https://bthome.io/) to allow easy control of [Home Assistant](https://www.home-assistant.io/) via Bluetooth advertisements. + +Other apps like [the Home Assistant app](https://banglejs.com/apps/?id=ha) communicate with Home Assistant +via your phone so work from anywhere, but require being in range of your phone. + +## Usage + +When the app is installed, go to the `BTHome` app and click Settings. + +Here, you can choose if you want to advertise your Battery status, but can also click `Add Button`. + +You can then add a custom button event: + +* `Icon` - the picture for the button +* `Name` - the name associated with the button +* `Action` - the action that Home Assistant will see when this button is pressed +* `Button #` - the button event 'number' - keep this at 0 for now + +Once you've saved, you will then get your button shown in the BTHome app. Tapping it will make Bangle.js advertise via BTHome that the button has been pressed. + +## ClockInfo + +When you've added one or more buttons, they will appear in a ClockInfo under the main `Bangle.js` heading. You can just tap to select the ClockInfo, scroll down until a BTHome one is visible and then tap again. It will immediately send the Advertisement. + diff --git a/apps/bthome/app-icon.js b/apps/bthome/app-icon.js new file mode 100644 index 000000000..ecdc205bc --- /dev/null +++ b/apps/bthome/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AAIHBy06nnnDiHwBRMDrgLJhtXBZM1qvABZHVqtwFxFVqowIhoLBGBE1q35GBHVrkDytyrAuGHIPVroLFFwODrklqoLFLoOCrALHLoIXILoVw+APBBYhdCsEAyphFFwITBgQDBMIgeBqtUgILCSQQuBrflBYW+SQYuBuENBYItB6owCXYUDBYIUBYYYuBh2wBYNQ9cFGAWlq0JsGUgNgy0J1WsEgMWhtwBYXXhWq1YLBkvD4HUgNwnk61Wq2ALBwEAkkBAYPq14kCktsgEMgZmBBIILDqoMBBQOWBIM61ALCrYLBh1WBYMKHgILBqxlBnILC2eqBYVVIAPlrWj1mg9QLDtkDyta1ns2AXEX4Va1c84YLEWYVa1XAhwLJ2B5BBZA6BBZOAC5UA5xHI1E8NYQAFh2g9hrCBY2vQYYAFgSPBF4QAFX4U6cgQLH9S/BAA2qcYYAG9WuPIILHOoKdBBY8D9WvgA")) \ No newline at end of file diff --git a/apps/bthome/app.js b/apps/bthome/app.js new file mode 100644 index 000000000..7e9a39531 --- /dev/null +++ b/apps/bthome/app.js @@ -0,0 +1,27 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +function showMenu() { + var settings = require("Storage").readJSON("bthome.json",1)||{}; + if (!(settings.buttons instanceof Array)) + settings.buttons = []; + var menu = { "": {title:"BTHome", back:load} }; + settings.buttons.forEach((button,idx) => { + var img = require("icons").getIcon(button.icon); + menu[/*LANG*/"\0"+img+" "+button.name] = function() { + Bangle.btHome([{type:"button_event",v:button.v,n:button.n}],{event:true}); + E.showMenu(); + E.showMessage("Sending Event"); + Bangle.buzz(); + setTimeout(showMenu, 500); + }; + }); + menu[/*LANG*/"Settings"] = function() { + eval(require("Storage").read("bthome.settings.js"))(()=>showMenu()); + }; + E.showMenu(menu); +} + +showMenu(); + + diff --git a/apps/bthome/boot.js b/apps/bthome/boot.js new file mode 100644 index 000000000..9c02581fe --- /dev/null +++ b/apps/bthome/boot.js @@ -0,0 +1,68 @@ +// Ensure we have the bleAdvert global (to play well with other stuff) +if (!Bangle.bleAdvert) Bangle.bleAdvert = {}; +Bangle.btHomeData = []; +{ + require("BTHome").packetId = 0|(Math.random()*256); // random packet id so new packets show up + let settings = require("Storage").readJSON("bthome.json",1)||{}; + if (settings.showBattery) + Bangle.btHomeData.push({ + type : "battery", + v : E.getBattery() + }); + // If buttons defined, add events for them + if (settings.buttons instanceof Array) { + let n = settings.buttons.reduce((n,b)=>b.n>n?b.n:n,-1); + for (var i=0;i<=n;i++) + Bangle.btHomeData.push({type:"button_event",v:"none",n:n}); + } +} + +/* Global function to allow advertising BTHome adverts + extras = array of extra data, see require("BTHome").getAdvertisement - can add {n:0/1/2} for different instances + options = { event : an event - advertise fast, and when connected + } +*/ +Bangle.btHome = function(extras, options) { + options = options||{}; + if(extras) { // update with extras + extras.forEach(extra => { + var n = Bangle.btHomeData.find(b=>b.type==extra.type && b.n==extra.n); + if (n) Object.assign(n, extra); + else Bangle.btHomeData.push(extra); + }); + } + var bat = Bangle.btHomeData.find(b=>b.type=="battery"); + if (bat) bat.v = E.getBattery(); + var advert = require("BTHome").getAdvertisement(Bangle.btHomeData)[0xFCD2]; + // Add to the list of available advertising + if(Array.isArray(Bangle.bleAdvert)){ + var found = false; + for(var ad in Bangle.bleAdvert){ + if(ad[0xFCD2]){ + ad[0xFCD2] = advert; + found = true; + break; + } + } + if(!found) + Bangle.bleAdvert.push({ 0xFCD2: advert }); + } else { + Bangle.bleAdvert[0xFCD2] = advert; + } + var advOptions = {}; + var updateTimeout = 10*60*1000; // update every 10 minutes + if (options.event) { // if it's an event... + advOptions.interval = 50; + advOptions.whenConnected = true; + updateTimeout = 30000; // slow down in 30 seconds + } + NRF.setAdvertising(Bangle.bleAdvert, advOptions); + if (Bangle.btHomeTimeout) clearTimeout(Bangle.btHomeTimeout); + Bangle.btHomeTimeout = setTimeout(function() { + delete Bangle.btHomeTimeout; + // clear events + Bangle.btHomeData.forEach(d => {if (d.type=="button_event") d.v="none";}); + // update + Bangle.btHome(); + },updateTimeout); +}; diff --git a/apps/bthome/clkinfo.js b/apps/bthome/clkinfo.js new file mode 100644 index 000000000..8698c9828 --- /dev/null +++ b/apps/bthome/clkinfo.js @@ -0,0 +1,17 @@ +(function() { + var settings = require("Storage").readJSON("bthome.json",1)||{}; + if (!(settings.buttons instanceof Array)) + settings.buttons = []; + return { + name: "Bangle", + items: settings.buttons.map(button => { + return { name : button.name, + get : function() { return { text : button.name, + img : require("icons").getIcon(button.icon) }}, + show : function() {}, + hide : function() {}, + run : function() { Bangle.btHome([{type:"button_event",v:button.v,n:button.n}],{event:true}); } + } + }) + }; +}) // must not have a semi-colon! \ No newline at end of file diff --git a/apps/bthome/icon.png b/apps/bthome/icon.png new file mode 100644 index 000000000..091784477 Binary files /dev/null and b/apps/bthome/icon.png differ diff --git a/apps/bthome/metadata.json b/apps/bthome/metadata.json new file mode 100644 index 000000000..c2767b9cf --- /dev/null +++ b/apps/bthome/metadata.json @@ -0,0 +1,20 @@ +{ "id": "bthome", + "name": "BTHome", + "shortName":"BTHome", + "version":"0.01", + "description": "Allow your Bangle to advertise with BTHome and send events to Home Assistant via Bluetooth", + "icon": "icon.png", + "type": "app", + "tags": "clkinfo,bthome,bluetooth", + "supports" : ["BANGLEJS2"], + "dependencies": {"textinput":"type", "icons":"module"}, + "readme": "README.md", + "storage": [ + {"name":"bthome.img","url":"app-icon.js","evaluate":true}, + {"name":"bthome.clkinfo.js","url":"clkinfo.js"}, + {"name":"bthome.boot.js","url":"boot.js"}, + {"name":"bthome.app.js","url":"app.js"}, + {"name":"bthome.settings.js","url":"settings.js"} + ], + "data":[{"name":"bthome.json"}] +} diff --git a/apps/bthome/settings.js b/apps/bthome/settings.js new file mode 100644 index 000000000..70f50f2ac --- /dev/null +++ b/apps/bthome/settings.js @@ -0,0 +1,91 @@ +(function(back) { + var settings = require("Storage").readJSON("bthome.json",1)||{}; + if (!(settings.buttons instanceof Array)) + settings.buttons = []; + + function saveSettings() { + require("Storage").writeJSON("bthome.json",settings) + } + + function showButtonMenu(button, isNew) { + var isNew = false; + if (!button) { + button = {name:"home", icon:"home", n:0, v:"press"}; + isNew = true; + } + var actions = ["press","double_press","triple_press","long_press","long_double_press","long_triple_press"]; + var menu = { + "":{title:isNew ? /*LANG*/"New Button" : /*LANG*/"Edit Button", back:showMenu}, + /*LANG*/"Icon" : { + value : "\0"+require("icons").getIcon(button.icon), + onchange : () => { + require("icons").showIconChooser().then(function(iconName) { + button.icon = iconName; + button.name = iconName; + showButtonMenu(button, isNew); + }, function() { + showButtonMenu(button, isNew); + }); + } + }, + /*LANG*/"Name" : { + value : button.name, + onchange : () => { + require("textinput").input({text:button.name}).then(function(name) { + button.name = name; + showButtonMenu(button, isNew); + }, function() { + showButtonMenu(button, isNew); + }); + } + }, + /*LANG*/"Action" : { + value : Math.max(0,actions.indexOf(button.v)), min:0, max:actions.length-1, + format : v => actions[v], + onchange : v => button.v=actions[v] + }, + /*LANG*/"Button #" : { + value : button.n, min:0, max:3, + onchange : v => button.n=v + }, + /*LANG*/"Save" : () => { + settings.buttons.push(button); + saveSettings(); + showMenu(); + } + }; + if (!isNew) menu[/*LANG*/"Delete"] = function() { + E.showPrompt("Delete Button?").then(function(yes) { + if (yes) { + settings.buttons.splice(settings.buttons.indexOf(button),1); + saveSettings(); + } + showMenu(); + }); + } + E.showMenu(menu); + } + + function showMenu() { + var menu = { "": {title:"BTHome", back:back}, + /*LANG*/"Show Battery" : { + value : !!settings.showBattery, + onchange : v=>{ + settings.showBattery = v; + saveSettings(); + } + } + }; + settings.buttons.forEach((button,idx) => { + var img = require("icons").getIcon(button.icon); + menu[/*LANG*/"Button"+(img ? " \0"+img : (idx+1))] = function() { + showButtonMenu(button, false); + }; + }); + menu[/*LANG*/"Add Button"] = function() { + showButtonMenu(undefined, true); + }; + E.showMenu(menu); + } + showMenu(); +}) \ No newline at end of file diff --git a/apps/bthometemp/metadata.json b/apps/bthometemp/metadata.json index 8ffb22c83..fc6804f17 100644 --- a/apps/bthometemp/metadata.json +++ b/apps/bthometemp/metadata.json @@ -2,7 +2,7 @@ "name": "BTHome Temperature and Pressure", "shortName":"BTHome T", "version":"0.02", - "description": "Displays temperature and pressure, and advertises them over bluetooth using BTHome.io standard", + "description": "Displays temperature and pressure, and advertises them over bluetooth for Home Assistant using BTHome.io standard", "icon": "app.png", "tags": "bthome,bluetooth,temperature", "supports" : ["BANGLEJS2"], diff --git a/apps/espruinoctrl/ChangeLog b/apps/espruinoctrl/ChangeLog index 819ae56cb..522cba63e 100644 --- a/apps/espruinoctrl/ChangeLog +++ b/apps/espruinoctrl/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Disable not existing BTN3 on Bangle.js 2, set maximum transmit power +0.03: Now use BTN2 on Bangle.js 1, and on Bangle.js 2 use the middle button to return to the menu \ No newline at end of file diff --git a/apps/espruinoctrl/README.md b/apps/espruinoctrl/README.md index 7b2e434e7..59c96b0de 100644 --- a/apps/espruinoctrl/README.md +++ b/apps/espruinoctrl/README.md @@ -14,7 +14,8 @@ with 4 options: with this address will be connected to directly. If not specified a menu showing available Espruino devices is popped up. * **RX** - If checked, the app will display any data received from the -device being connected to. Use this if you want to print data - eg: `print(E.getBattery())` +device being connected to (waiting 500ms after the last data before disconnecting). +Use this if you want to print data - eg: `print(E.getBattery())` When done, click 'Upload'. Your changes will be saved to local storage so they'll be remembered next time you upload from the same device. @@ -25,4 +26,9 @@ Simply load the app and you'll see a menu with the menu items you defined. Select one and you'll be able to connect to the device and send the command. -If a command should wait for a response then +The Bangle will connect to the device, send the command, and if: + +* `RX` isn't set it will disconnect immediately and return to the menu +* `RX` is set it will listen for a response and write it to the screen, before +disconnecting after 500ms of inactivity. To return to the menu after this, press the button. + diff --git a/apps/espruinoctrl/custom.html b/apps/espruinoctrl/custom.html index 2329ad214..27ef1eb53 100644 --- a/apps/espruinoctrl/custom.html +++ b/apps/espruinoctrl/custom.html @@ -194,16 +194,14 @@ function sendCommandRX(device, text, callback) { function done() { Terminal.println("\\n============\\n Disconnected"); device.disconnect(); - if (global.BTN3 !== undefined) { - setTimeout(function() { - setWatch(function() { - if (callback) callback(); - resolve(); - }, BTN3); - g.reset().setFont("6x8",2).setFontAlign(0,0,1); - g.drawString("Back", g.getWidth()-10, g.getHeight()-50); - }, 200); - } + setTimeout(function() { + setWatch(function() { + if (callback) callback(); + resolve(); + }, (process.env.HWVERSION==2) ? BTN1 : BTN2); + g.reset().setFont("6x8",2).setFontAlign(0,0,1); + g.drawString("Back", g.getWidth()-10, g.getHeight()/2); + }, 200); } device.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e").then(function(s) { service = s; diff --git a/apps/espruinoctrl/metadata.json b/apps/espruinoctrl/metadata.json index 9308b4a46..4f5fa01c8 100644 --- a/apps/espruinoctrl/metadata.json +++ b/apps/espruinoctrl/metadata.json @@ -2,7 +2,7 @@ "id": "espruinoctrl", "name": "Espruino Control", "shortName": "Espruino Ctrl", - "version": "0.02", + "version": "0.03", "description": "Send commands to other Espruino devices via the Bluetooth UART interface. Customisable commands!", "icon": "app.png", "tags": "tool,bluetooth", diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index b917da87b..b2e5b37fe 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -3,7 +3,7 @@ -

This tool allows you to update the firmware on Bangle.js 2 devices +

This tool allows you to update the firmware on Bangle.js 2 devices from within the App Loader.

@@ -32,7 +32,7 @@ bit of code that runs when Bangle.js starts, and it is able to update the Bangle.js firmware. Normally you would update firmware via this Firmware Updater app, but if for some reason Bangle.js will not boot, you can - always use DFU to do the update manually. + always use DFU to do the update manually. On DFU 2v19 and earlier, iOS devices could have issues updating firmware - 2v20 fixes this.

DFU is itself a bootloader, but here we're calling it DFU to avoid confusion with the Bootloader app in the app loader (which prepares Bangle.js for running apps).

@@ -42,7 +42,7 @@