Gadgetbridge for Android

Gadgetbridge is an Android application that allows you to use smartwatch-style notifications and health monitoring without the need for a proprietary application or web service. We have a modified Bangle.js Gadgetbridge app on the Google Play Store or F-Droid (see below)

If you like Gadgetbridge, please consider donating to help support its continued development

How to set up

Extra Setup

Does Gadgetbridge keep disconnecting from your Bangle? It may be that your phone is doing some 'battery usage optimisation' and deciding that Gadgetbridge should be shut down. See https://dontkillmyapp.com/ for device-specific advice on how to stop this happening.

By default, some features are disabled in Gadgetbridge and you may well want to enable them:

On some phones, even though Gadgetbridge requests permissions, they may not have been granted by default:

If you're using the Play Store Gadgetbridge, you can also sign up to be a tester - occasionally we will release a new version for testing before rolling it out to everyone and you'll get access to that.

Bangle.js Gadgetbridge app

We have a version of Gadgetbridge for Bangle.js that allows Internet Access (normal Gadgetbridge does not). It is available from:

The Bangle.js Gadgetbridge app is built from the same source code as the normal Gadgetbridge, however the Bangle.js Gadgetbridge app requires extra internet permissions to install and so can provide extra features:

HTTP requests

Must be enabled first by clicking the gear icon next to the Bangle.js you're connected to in Gadgetbridge, and then enabling Allow Internet Access

On Bangle.js just do something like this to make an HTTP request:

Bangle.http("https://pur3.co.uk/hello.txt").then(data=>{
  console.log("Got ",data);
});

For more information check out the Android Integration app's Read more... link.

Right now you must use HTTPS (HTTP is not supported). The low-level implementation is described in How it works internally below.

Intents

Must be enabled first by clicking the gear icon next to the Bangle.js you're connected to in Gadgetbridge, and then enabling Allow Intents

Bangle -> Android

On Bangle.js send something like:

Bluetooth.println(JSON.stringify({t:"int­ent",action:"com.sonyericsson.alarm.ALAR­M_ALERT",extra:{key1:"asdfas"}}));

This will send a Global Android intent which can cause certain apps/windows to open, or can be used with apps like Tasker.

Or:

Bluetooth.println(JSON.stringify({t:"intent", target:"activity", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", flags:["FLAG_ACTIVITY_NEW_TASK"], categories:["android.intent.category.DEFAULT"], extra:{"query":'track:"Sittin\' on the Dock of the Bay" artist:"Otis Redding"'}}))

This will search for and play the song "Sittin' on the Dock of the Bay". The android device will ask about what app to use. The flag "FLAG_ACTIVITY_NEW_TASK" is needed in order for the activity to launch in this case.

Gadgetbridge connected to a Bangle.js watch can broadcast intents and start activities or services.

Toggling play/pause of the android music app Poweramp can be done via its API-service:

Bluetooth.println(JSON.stringify({t:"intent", target:"foregroundservice", action:"com.maxmpz.audioplayer.API_COMMAND", package:"com.maxmpz.audioplayer", extra:{cmd:"TOGGLE_PLAY_PAUSE"}}));

Services can act while the android device is locked and/or sleeping. Activities cannot. A way around this is to fire this intent that wakes and unlocks the device:

Bluetooth.println(JSON.stringify({t:"intent", target:"activity", flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_CLEAR_TASK", "FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS", "FLAG_ACTIVITY_NO_ANIMATION"], package:"gadgetbridge", class:"nodomain.freeyourgadget.gadgetbridge.activities.WakeActivity"}));

If the waking intent doesn't work then try sending it twice in a row. If that doesn't do it, make sure to add the Bangle.js as a trusted device in android settings for it to be able to bypass the lock screen. If it still doesn't work, try re-adding the Bangle.js via Gadgetbridge with "CompanionDevice Pairing" activated.

The following type of information can be supplied for intents: target, action, flags, categories, package, class, mimetype, data and extra. Values to pass with the target-key are "broadcastreceiver", "activity", "service" or "foregroundservice" (falls back to "service" if below Android 8.0). Intents will default to being broadcast if no target is specified. To accommodate the different Gadgetbridge versions a special package-value, "gadgetbridge", can be supplied with the package-key.

Template for initiating an intent from a Bangle.js app:

Bluetooth.println(JSON.stringify({t:"intent", target:"", action:"", flags:["flag1", "flag2",...], categories:["category1","category2",...], package:"", class:"", mimetype:"", data:"", extra:{someKey:"someValueOrString", anotherKey:"anotherValueOrString",...}}));

Key/value-pairs can be omitted if they are not needed.

The main resource on android intents is the android documentation intent reference. For inspiration search for "tasker intent" in your favourite search engine.

Android -> Bangle

On the Android device, you can send code to execute to your Bangle.js (Programmable must be set to true in the Bangle's settings).

Just send an intent to com.banglejs.uart.tx, with Extra Data of line set to the JavaScript to execute. For example to display a variable from Tasker on the Bangle's LCD (scrolling everything else up), set up:

Action: com.banglejs.uart.tx
Cat: None
Extra: line:Terminal.println(%avariable)
Target: Broadcast Receiver
Variable: Number, Configure on Import, NOT structured, Value set, Nothing Exported, NOT Same as value

Weather

You can also get weather from Gadgetbridge. Install the Weather Widget and check out the Read more... link on the app page for more information on the setup required. An additional app is required to forward the current weather into Gadgetbridge.

If you're using the Play Store 'Bangle.js Gadgetbridge' app, you need to set the package name to com.espruino.gadgetbridge.banglejs

Sports Activity Sync

Activities recorded with the "Recorder" app can be synced to Gadgetbridge which will store, parse and display them in the app.

Activities with GPS data can be forwarded from Gadgetbridge to other apps via a GPX file. If there're no GPS coordinates logged at the beginning of the activity, the forwarded information will not include these first data points and the starting time will not be the same. To mitigate this make sure you have a GPS fix before starting to record on the watch (updated A-GPS data drastically improve the time to get a first fix).

More info at https://gadgetbridge.org/basics/features/sports/ .

How it works internally

Messages sent to Bangle.js from Phone

Messages are wrapped in the text "\x10" + "GB(...)\n", so that if they're sent to a normal Espruino REPL the GB function will be executed with the supplied data as the first argument.

Currently implemented messages are:

Bangle.js Gadgetbridge also provides:

For example:

// new message
GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"})
// message changed
GB({"t":"notify~","id":1575479849,"body":"this changed"})
// remove message
GB({"t":"notify-","id":1575479849});
// maps navigation
GB({"t":"notify","id":1,"src":"Maps","title":"0 yd - High St","body":"Campton - 11:48 ETA","img":"Y2MBAA....AAAAAAAAAAAAAA="})
// music
GB({"t":"musicstate","state":"play","position":0,"shuffle":1,"repeat":1})
GB({"t":"musicinfo","artist":"My Artist","album":"My Album","track":"Track One","dur":241,"c":2,"n":2})
// Call coming in
GB({"t":"call","cmd":"incoming","name":"name","number":"+441234123123"})
// Set a single alarm, 6:30am, every day of the week
GB({"t":"alarm", "d":[{"h":"6","m":"30:","rep":127}]})
// Send a GPS location
GB({"t":"gps","lat":51.509865,"lon":-0.118092,"alt":42,"speed":0,"course":123,"time":1684413470805,"satellites":11,"hdop":10.720000267028809,"externalSource":true,"gpsSource":"GPS"})
// Send a navigation message
GB({"t":"nav","instr":"High St towards Tollgate Rd","distance":"966yd","action":"continue","eta":"08:39"})

Messages from Bangle.js to Phone

Any line beginning with { will be parsed as JSON by Gadgetbridge, so to send a command, simply use Bluetooth.println(JSON.stringify(json)).

Available message types are:

Bangle.js Gadgetbridge also provides:

For example:

Bluetooth.println(JSON.stringify({t:"info", msg:"Hello World"}))

will display a message on your phone's screen.

Debugging

You can click Debug -> Fetch Device Debug Logs in Gadgetbridge which will save a log of all data sent to/from Bangle.js to a file on your phone. This is very helpful for debugging and will show if any exceptions/errors have happened on the Bangle, and what commands caused them. You can then connect with the Web IDE and re-issue those commands by copy/pasting them into the IDE's left hand side to help you reproduce.

There's a Gadgetbridge Debug app you can install. When running this will show you the data that is being received from Gadgetbridge. See Read more... next to the app for more information.

Once you know the command that caused the problem you can then disconnect Gadgetbridge, connect with the Web IDE and issue that command by pasting it into the left-hand side of the IDE - for example:

GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"})

If there are any errors shown you'll be able to see them and use them to debug what is happening.

Remote Debugging

You can also connect the Web IDE to Bangle.js through your phone running Gadgetbridge.

From Gadgetbridge, start the App Loader, then go to More... and click Web IDE Remote.

You'll see a UUID shown - copy this and 'share' it with yourself, so you can then go to https://www.espruino.com/ide/ on your desktop, go to Settings, Communications, and paste it into the box for Remote Connection Bridge Peer ID.

Refresh the Web IDE page and (as long as the App Loader stays open in Gadgetbridge after Web IDE Remote has been pressed) you'll be able to connect via the Web IDE and see what Bangle.js is responding with as notifications/etc arrive.

Building Gadgetbridge

If you want to build Gadgetbridge yourself there's proper documentation at https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Developer-Documentation

This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.