Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
New Device Tutorial
Supporting a new device in Gadgetbridge
This is a step by step tutorial for supporting a new device in Gadgetbridge. There are some differences depending on the transport layer being used (Bluetooth Classic, Bluetooth LE, WiFi, ...), but most of it is independent of that. The tutorial only covers the basics to get you started quickly. For more details, have a look at the existing implementations for other devices. Try to do your implementation in a similar way (where it makes sense), so as to ease maintenance.
Before going into the details, let's have a short look at the process the user has to go through in order to connect a new device.
Start Device Discovery -> Select one of the displayed devices -> If necessary: pair/authenticate with the device -> If necessary: provide certain settings like nick name, age, height, ... -> Initialize the device -> Device can be used
For this tutorial we will add support for the exemplary SuperBand 4000 device, so many things are named after that.
Part 1: Discovery
The first part deals with discovering SuperBand 4000 devices and telling Gadgetbridge that/how they are supported.
- Add a new device type constant SUPERBAND_4000 to
nodomain.freeyourgadget.gadgetbridge.model.DeviceType. Pick a new number as the
keyand leave 10 numbers "room" to the last number. These are reserved so that related devices can have nearby numbers. Also specify a default icon (coloured) and a disabled icon (greyscale). If you don't have any yet, reuse some other icons.
- Create a new package
- In that package, create a class
nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator. This class tells Gadgetbridge whether a discovered device is supported and what features are supported (with the implementation in Gadgetbridge, not in general).
- Implement the method
getDeviceType()and return the constant
DeviceType.SUPERBAND_4000that you previously added.
- If your device is a Bluetooth LE device, override the method
createBLEScanFilters()and return a list of
ScanFilters for recognizing your device during discovery by a Bluetooth service UUID for example. You can skip this if you cannot or don't know how to recognize your device that way yet.
- Implement the method
DeviceType getSupportedType(GBDeviceCandidate candidate). This method will be called during discovery in order to check wether the discovered device is supported by Gadgetbridge. To decide this, you might check further services, the MAC address, or even the device name if you don't know a better way, yet. If you're determined to support the given device candidate, you return the recognized
DeviceType. Typically this is the one that you return in
getDeviceType(). If you do not recognize the given candidate, return
DeviceType.UNKNOWNso that another
DeviceCoordinatorcan be asked.
getBondingStyle()depending on how your device needs to be paired on the Bluetooth level. Return
BONDING_STYLE_BONDto perform BLE pairing,
BONDING_STYLE_ASKto let the user decide that during discovery, or
BONDING_STYLE_NONEto not perform BLE pairing at all.
- If your device needs some very special kind of pairing/bonding/authentication before it can be used, you may override the method
getPairingActivity()in which you return an
Activityclass that will be shown for your device after the device discovery process. Otherwise, just return
- There are several more methods that you need to implement, mostly
XXXis a certain feature a device may support or not. As soon as you implement support for one such feature, make sure to announce it by returning
truein the corresponding
supportsXXX()method. Otherwise the feature will not be available in Gadgetbridge.
- Implement the method
- Register your
nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper#createCoordinators()so that it will be used.
So, that was the first part. With these changes, Gadgetbridge should be able to find and display your device in the Discovery view. If that is not the case, add breakpoints in your device coordinator's
getSupportedType() method to find out why. Also check the
ScanFilters, if any. Only once your device is found and displayed during discovery, does it make sense to continue with the next steps.
Part 2: Communication
The next part deals with the communication between Gadgetbridge and your device. This part is very specific to the device and the communication protocol being used.
This code lives in a separate package because it is used by a contiuously running background
Service. This service is the
- Create the package
- Create a
SuperBand4000DeviceSupportclass in that package. As the super class, choose one of the existing abstract classes like
nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport, depending on the transport layer.
nodomain.freeyourgadget.gadgetbridge.service.DeviceSupportFactory#createBTDeviceSupport()and add the code to instantiate your support class for
For Bluetooth Classic with
AbstractSerialDeviceSupport as super class, you will usually create at least two other classes: a
SuperBand4000IOThread and a
*IOThreadclass manages the Bluetooth rfcomm socket in a non-blocking way for callers.
*Protocolclass understands and handles the incoming and outgoing messages.
For Bluetooth LE, you will use the
nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue classes to communicate with the device via GATT events. Theses classes will take care of synchronizing everything.
See the subclasses of
nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile for some ready-to-be-used implementations of standard BLE services/profiles.
We hope that this tutorial will help you get started with adding support for new devices in Gadgetbridge.
For questions and improvements, do not hesitate to contact us!
Happy hacking, the Gadgetbridge Team
slf4j for logging, so just use
LoggerFactory.getLogger(Your.class) and log away. The output will be written to the Android Log (so you can get it with logcat or Android Studio) as well as to the file
/sdcard/Android/data/nodomain.freeyourgadget.gadgetbridge/files/gadgetbridge.log. File logging needs to be enabled in Gadgetbridge's preferences, first.
Use one of the
nodomain.freeyourgadget.gadgetbridge.util.GB#toast() methods to display information to the user. They
- not only display, but also log warnings and errors
- can safely be called from a background thread
greenDAO for database access. See
nodomain.freeyourgadget.gadgetbridge.daogen.GBDaoGenerator for entity definition and generation.