Code Monkey home page Code Monkey logo

bluetooth-manager's Introduction

Maven Central Build Status Coverage Status Codacy Badge Join the chat at https://gitter.im/sputnikdev/bluetooth-manager

bluetooth-manager

Java Bluetooth Manager. A library/framework for managing bluetooth adapters, bluetooth devices, GATT services and characteristics

The Bluetooth Manager is a set of java APIs which is designed to streamline all the hard work of dealing with unstable by its nature Bluetooth protocol.

KPIs

The following KPIs were kept in mind while designing and implementing the Bluetooth Manager:

  1. Flexibility in using different transports, e.g. serial port, dbus or any other (like tinyb).
  2. Extensibility in adding new supported devices, e.g. different sensors and other hardware.
  3. Robustness. Due to the nature of the Bluetooth protocol the biggest challenge is making the API stable enough so that end-users could use it.
  4. Comprehensive support for Bluetooth GATT specifications. This is a powerful feature which would allow users:
    1. add any device which conforms GATT specification without developing any custom code
    2. add custom made devices by only specifying a path to a custom defined GATT specification for a device

Implementation overview

The following diagram outlines some details of the Bluetooth Manager: Bluetooth Manager diagram

Governors API

The central part of the BM architecture is "Governors" (examples and more info BluetoothGovernor,
AdapterGovernor, DeviceGovernor and BluetoothManager). These are the components which define lifecycle of BT objects and contain logic for error recovery. They are similar to the transport APIs (see below), but yet different because they are "active" components, i.e. they implement some logic for each of BT objects (adapter, device, characteristic) that make the system more robust and enable the system to recover from unexpected situations such as disconnections and power outages.

Apart from making the system stable, the Governors are designed in a such way that they can be used externally, in other words it is another abstraction layer which hides some specifics/difficulties of the BT protocol behind user-friendly APIs.

Transport API

A specially designed abstraction layer (transport) is used to bring support for various bluetooth adapters/dongles, operation systems and hardware architecture types.

The following diagram outlines some details of the Bluetooth Manager Transport abstraction layer: Transport diagram

There are two implementations of the BT Transport currently:

  • TinyB Transport. The TinyB transport brings support for:
    • Conventional USB bluetooth dongles.
    • Linux based operation systems.
    • A wide range of hardware architectures (including some ARM based devices, e.g. Raspberry PI etc).
  • WIP: Bluegiga Transport. The Bluegiga transport brings support for:
    • Bluegiga (BLE112) USB bluetooth dongles.
    • Linux, Windows and OSX based operation systems.
    • A wide range of hardware architectures (including some ARM based devices, e.g. Raspberry PI etc).

Compatibility matrix

TinyB Bluegiga
Windows - Y
Linux Y Y
Mac - Y
X86 32bit Y Y
X86 64bit Y Y
ARM v6 (Raspberry PI) Y Y
Adapters autodiscovery Y Y
Adapter power management Y -
Adapter aliases Y -
BLE devices discovery Y Y
BR/EDR devices discovery (legacy BT) Y -

Troubleshooting

Using Bluetooth Manager

Start using it by specifying maven dependencies from the Maven Central repository:

<dependency>
    <groupId>org.sputnikdev</groupId>
    <artifactId>bluetooth-manager</artifactId>
    <version>X.Y.Z</version>
</dependency>
<dependency>
    <groupId>org.sputnikdev</groupId>
    <artifactId>bluetooth-manager-tinyb</artifactId>
    <version>X.Y.Z</version>
</dependency>

The example below shows how to set up the Bluetooth Manager and read a characteristic value.

Reading characteristic

import org.sputnikdev.bluetooth.URL;
import org.sputnikdev.bluetooth.manager.CharacteristicGovernor;
import org.sputnikdev.bluetooth.manager.impl.BluetoothManagerBuilder;

public final class BluetoothManagerSimpleTest {

    public static void main(String[] args) throws Exception {
        new BluetoothManagerBuilder()
                .withTinyBTransport(true)
                .withBlueGigaTransport("^*.$")
                .build()
                .getCharacteristicGovernor(new URL("/XX:XX:XX:XX:XX:XX/F7:EC:62:B9:CF:1F/" 
                        + "0000180f-0000-1000-8000-00805f9b34fb/00002a19-0000-1000-8000-00805f9b34fb"), true)
                .whenReady(CharacteristicGovernor::read)
                .thenAccept(data -> {
                    System.out.println("Battery level: " + data[0]);   
                }).get();
    }
    
}

Here is what happening behind the scene in the example above:

  • detecting what adapters are installed in the system (Generic and BlueGiga)
  • automatically loading native libraries for the current architecture type (CPU type and OS type)
  • setting up bluetooth manager
  • choosing the nearest bluetooth adapter
  • connecting to the bluetooth device
  • resolving GATT services and characteristics
  • reading the "Battery Level" characteristic

Receiving characteristic notifications

import org.sputnikdev.bluetooth.URL;
import org.sputnikdev.bluetooth.manager.BluetoothManager;
import org.sputnikdev.bluetooth.manager.impl.BluetoothManagerBuilder;

public class BluetoothManagerSimpleTest {

    public static void main(String args[]) {
        // get the Bluetooth Manager
        BluetoothManager manager = new BluetoothManagerBuilder()
                .withTinyBTransport(true)
                .withBlueGigaTransport("^*.$")
                .build();
        // define a URL pointing to the target characteristic
        URL url = new URL("/88:6B:0F:01:90:CA/CF:FC:9E:B2:0E:63/" +
                "0000180f-0000-1000-8000-00805f9b34fb/00002a19-0000-1000-8000-00805f9b34fb");
        // subscribe to the characteristic notification
        manager.getCharacteristicGovernor(url, true).addValueListener(value -> {
            System.out.println("Battery level: " + value[0]);
        });
        // do your other stuff
        Thread.sleep(10000);
    }
}

More examples here: bluetooth-cli


Contribution

You are welcome to contribute to the project, the project environment is designed to make it easy by using:

  • Travis CI to release artifacts directly to the Maven Central repository.
  • Code style rules to support clarity and supportability. The results can be seen in the Codacy.
  • Code coverage reports in the Coveralls to maintain sustainability. 100% of code coverage with unittests is the target.

The build process is streamlined by using standard maven tools.

To build the project with maven:

mvn clean install

To cut a new release and upload it to the Maven Central Repository:

mvn release:prepare -B
mvn release:perform

Travis CI process will take care of everything, you will find a new artifact in the Maven Central repository when the release process finishes successfully.

bluetooth-manager's People

Contributors

maggu2810 avatar meccup avatar vkolotov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bluetooth-manager's Issues

Exposing BT Service as an Example

Hi Vlad
Thank you for this great BT libraries. I try to expose a simple BT service that I can consume from a mobile phone for educational reasons. I was tried to and was looking for a small example to do that with your Stack, but it is simply to overwhelming.
Is it possible that you can point me to, or create, a small example that exports a BT Service that can be discovered with your Stack? It would maybe also help other to get started with this.
Thank you,
Markus

Problem writing value to characteristic

I created an iOS app peripheral and I am trying to create a java/kotlin cli app write data to the peripheral. The kotlin cli app can see the iOS app as a peripheral but whenever I call manager.getCharacteristicGovernor(url) the characteristic is never ready. Would you be able to look at my code and see if I am missing something?

import org.sputnikdev.bluetooth.manager.CharacteristicGovernor
import org.sputnikdev.bluetooth.manager.impl.BluetoothManagerBuilder

object BmSendTest {

    private val serviceId = "56a7c54d-fd39-4efe-9e10-4d832fa64b6f".toUpperCase()
    private val characteristic = "3348f88a-4972-4125-a6fb-6c70ef459e4d".toUpperCase()

    private val SEND_VALUE = "43966666".encodeToByteArray()

    @JvmStatic
    private fun sendValue(governor: CharacteristicGovernor): Boolean {
        println("sending: $SEND_VALUE")
        return governor.write(SEND_VALUE)
    }

    @Throws(Exception::class)
    @JvmStatic
    fun main(args: Array<String>) {
        println("Starting BLE Requests")
        val manager = BluetoothManagerBuilder()
            .withTinyBTransport(true)
            .withBlueGigaTransport("^*.$")
            .withIgnoreTransportInitErrors(true)
            .withDiscovering(true)
            .withRediscover(true)
            .build()

        manager.addDeviceDiscoveryListener { discoveredDevice ->
            if (discoveredDevice.displayName == "iOS Peripheral") {
                val d = manager.getDeviceGovernor(discoveredDevice.url)
                d.connectionControl = true
                println(
                    "=== Device: ${d.displayName}," +
                            " isOnline: ${d.isOnline}," +
                            " isAuthenticated: ${d.isAuthenticated}," +
                            " isBleEnabled: ${d.isBleEnabled}," +
                            " isBlocked: ${d.isBlocked}," +
                            " isConnected: ${d.isConnected}," +
                            " isServicesResolved: ${d.isServicesResolved}," +
                            " isReady:${d.isReady}"
                )
                val url = discoveredDevice.url.copyWith(serviceId, characteristic)
                println(url)
                // ISSUE: characteristic is never ready.
                manager.getCharacteristicGovernor(url).whenReady(BmSendTest::sendValue)
            }
        }
        manager.start(true)
    }
}

Console output:

Starting BLE Requests

(process:49679): GLib-CRITICAL **: 10:20:00.860: g_variant_iter_loop: assertion 'first_time || format_string == GVSI(iter)->loop_format' failed

(process:49679): GLib-CRITICAL **: 10:20:00.860: g_variant_iter_free: assertion 'is_valid_heap_iter (iter)' failed
=== Device: iOS Peripheral, isOnline: false, isAuthenticated: false, isBleEnabled: true, isBlocked: false, isConnected: false, isServicesResolved: false, isReady:true
tinyb:/XX:XX:XX:XX:XX:XX/57:50:6A:3B:53:0A/56a7c54d-fd39-4efe-9e10-4d832fa64b6f/3348f88a-4972-4125-a6fb-6c70ef459e4d
=== Device: iOS Peripheral, isOnline: true, isAuthenticated: false, isBleEnabled: true, isBlocked: false, isConnected: true, isServicesResolved: false, isReady:true
tinyb:/XX:XX:XX:XX:XX:XX/57:50:6A:3B:53:0A/56a7c54d-fd39-4efe-9e10-4d832fa64b6f/3348f88a-4972-4125-a6fb-6c70ef459e4d

I'm running this on manjaro and eventually raspbian.

Changes I've tried to resolve the issue:

  • Tried jdk's 14, 13, 11
  • Tried running with sudo.

I was able to perform a test write to the peripheral using LightBlue https://punchthrough.com/lightblue/

Thanks for your help.

Tweaking responsiveness of the governors control methods

Bluetooth manager governors have various control fields (that control state of bluetooth objects). When a control field gets set, it takes some time for the thread scheduler to kick off and update governor state accordingly with control fields. A triggering mechanism must be implemented that makes governors to be more responsive.

Add support for advertising data

Bluetooth device advertizing packets must be exposed to bluetooth manage clients, such us:

  • Manufacturer data
  • Services data
  • Random/Public device address

Skip execution of governors if already running

If a device gets offline, then tinyb transport process to update governor status takes more time than usual and eventually times out. If the update process takes more than scheduled time to update governors, then thread workers get accumulated and blocked.

In order to prevent this, a mechanism must be implemented to detect if a governor already being updated by a process (thread).

BluetoothManagerBuilder Example + Questions

Hello sputnikdev,

Really cool BT framework you got here. :-)

I was trying to use it and I Tried to create the Bluetooth Manager but somehow I cannot include the BluetoothManagerBuilder:
import org.sputnikdev.bluetooth.manager.impl.BluetoothManagerBuilder
bt_manager = new BluetoothManagerBuilder().withTinyBTransport(true).build()
The import fails. :-(

Also do you an example on how to to make a simple discover connect and read a characteristic?
I have gotten as far as trying like this...

bt_manager.start(true)
Set discoveredDevices = bt_manager.getDiscoveredDevices()
discoveredDevices.each { device ->
println(device.getName())
}

Am I on the right track?

Also When including the BlueGiga Lib I get a following error:

Could not find com.zsmartsystems.bluetooth.bluegiga:com.zsmartsystems.bluetooth.bluegiga:1.0.0-SNAPSHOT.

Once again, awesome framework!!!
:-)

Bluegiga Connection times out after a few seconds

Hi! Thank you first of all for being the only option out there to implement Java bluetooth development on a Windows machine.

I've made an SPO2 continuous monitoring software using your asynchronous heart rate monitor. I use a Bluegiga BLE112 dongle that connects via bluetooth to an Arduino connected to a pulse oximeter. However, once a connection has been established and a few seconds of data has been received by the software, it stops, and after ten or so seconds, we get these warnings:

18:21:56.079 WARN Disconnection event received bluegiga:/88:6B:0F:C9:CA:59/F7:FA:FA:D5:1E:9C. Reason: CONNECTION_TIMEOUT.
18:22:07.084 WARN Timeout received while calling complex procedure: BlueGigaFindInformationFoundEvent / BlueGigaProcedureCompletedEvent. Trying one more time
18:22:07.087 WARN Could not discover device attributes: bluegiga:/88:6B:0F:C9:CA:59/F7:FA:FA:D5:1E:9C
org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaProcedureException: Could not initiate process: BlueGigaFindInformationFoundEvent / BlueGigaProcedureCompletedEvent / WRONG_STATE at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaHandler.callProcedure(BluegigaHandler.java:476) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaHandler.syncCallProcedure(BluegigaHandler.java:411) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaHandler.getCharacteristics(BluegigaHandler.java:213) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaDevice.discoverCharacteristics(BluegigaDevice.java:505) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaDevice.lambda$discoverAttributes$2(BluegigaDevice.java:435) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaHandler.runInSynchronizedContext(BluegigaHandler.java:190) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaDevice.discoverAttributes(BluegigaDevice.java:428) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaDevice.handleConnectionStatusEvent(BluegigaDevice.java:478) at org.sputnikdev.bluetooth.manager.transport.bluegiga.BluegigaDevice.bluegigaEventReceived(BluegigaDevice.java:283) at com.zsmartsystems.bluetooth.bluegiga.BlueGigaSerialHandler$2.run(BlueGigaSerialHandler.java:471) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:844)
18:22:12.108 WARN Could not discover device attributes: bluegiga:/88:6B:0F:C9:CA:59/F7:FA:FA:D5:1E:9C

On top of setting that characteristic governors and listeners as you did in your example, the only extra thing I do is check for connectivity by getting a device governor and returning isReady().
Is this an issue with your library or how I am implementing it? If not, is there a way for me to reset the connection to the arduino and reconnect once I have detected there to be a timeout? Also, is there a way for me to set my own timeout length so that the software reacts faster to an event such as this?

remove dependency to com.zsmartsystems.bluetooth.bluegiga snapshot

Hi,
currently if you want to run some code it dependes on
<dependency> <groupId>com.zsmartsystems.bluetooth.bluegiga</groupId> <artifactId>com.zsmartsystems.bluetooth.bluegiga</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency>

publish that library or remove the denepndency to be able to use bluetooth-manager without hacks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.