This project is a fork of the
libble.git project. If you have that one
already cloned locally, you can use
git clone --reference /path/to/your/libble.git/incarnation mirror_URL
to save bandwidth during cloning.
Deprecation notice
The libble project's features have moved into the
libsigrok library on 2019-06-04.
This version here is out of maintenance.
libble, a BLE communication helper library
This library supports serial communication over Bluetooth, especially to
measurement devices which use Bluetooth Low Energy. The intention is to
integrate the library with the sigrok project, similar
to the libserialport library.
The implementation of the library started from the GPLv3 licensed
mrnuke's experiment and
got modified to support more platforms in the future.
The library implements an RFCOMM client which can connect to an
RFCOMM server, as well as a BLE central which can connect to
BLE peripherals.
Current status
- Uses CMake, thus shall build and install on all major platforms (but
see below for source code portability).
- The library API is platform agnostic, shall be portable enough to work
on all platforms supported by sigrok.
- The library's internal implementation currently assumes Linux, uses
AF_BLUETOOTH
sockets and BlueZ headers (introduces new unconditional
build dependency: libbluetooth-dev
).
- Assumes that BLE devices use cable extender mode. Sends an initial
characteristic value to one handle, then keeps reading from another
handle. Grabs payload data from indications (tested) as well as
notifications (untested).
- Was tested with an EEVBlog 121GW
multimeter (builtin BLE122 module). Owon OW18B may work in similar
ways (TI CC254x module). Uni-T UT-D07 status is unknown.
- Also supports BT Classic by means of an RFCOMM client mode, which only
got tested with a DIY RFCOMM server, not a measurement device.
Build the library
There's nothing fancy to it, straight cmake approach, like so:
$ mkdir build; cd build; cmake ..
$ [ cmake -DCMAKE_INSTALL_PREFIX=$HOME .; ccmake . ]
$ make
$ [ make install ]
Example use
See the builtin help
Select device address, see raw bytes in text and binary format
$ ADDR=88:6B:12:34:56:78
$ ./ble-test -m $ADDR -r 8 -c 9 -C 0x0003
$ ./ble-test -m $ADDR
$ ./ble-test -m $ADDR -b | hexdump -Cv
Feed a COM port
This example assumes a loopback between two COM ports. Notice that COM
port loopback becomes obsolete when libsigrok grows native libble support.
$ COM_FEED=/dev/ttyUSB1; COM_READ=/dev/ttyUSB0
$ ( exec > $COM_FEED; exec < $COM_FEED; stty 115200; ./ble-test -m $ADDR -b ) &
$ sigrok-cli -d eevblog-121gw:conn=$COM_READ --scan
$ sigrok-cli -d eevblog-121gw:conn=$COM_READ --samples 100
Scan for BT devices
Notice that LE scan may require priviledges, depending on the internal
implementation and/or the availability of external components (and their
versions).
Communicate to an RFCOMM server
$ SRV_ADDR=11:22:33:44:55:66
$ [ ./rfcomm-test & ]
$ ./ble-test -m $SRV_ADDR -R 1 -d 100
$ [ kill $! ]
Known issues, TODO items
- Improve robustness. Optionally re-connect and re-initiate reception
upon connection loss, from previously cached parameters? Could apply
to both RFCOMM as well as BLE indications/notifications, but apps
may differ in their preference. In either case, apps must be able to
learn of errors, even when auto-recovery applies.
- Improve usability. Handle timeouts during connect, which currently
blocks indefinitely when the specified peer does not become available.
- Do integrate with libsigrok's infrastructure. Provide a namespace in
the serial layer (assumes serial-over-HID as a foundation) for simple
devices like DMMs. Optionally allow "deep" access from individual
drivers for more complex devices or unusual communication approaches
(other than notify/indicate or RFCOMM server). [ Update: an experiment
successfully used serial-dmm with EEVBlog 121GW without COM loopback. ]
- Come up with the appropriate
conn=
syntax. Like conn=bt/ble122/<addr>
or conn=bt/ti-cc254x/<addr>
etc for BLE, optionally followed by handle
and value specs (while their defaults result from the ble122 etc
"profile" names). Or conn=bt/rfcomm/<addr>
for BT classic and RFCOMM
channels, optionally followed by the channel number (default 1).
[ Update: The experiment successfully used the above straight forms.
It's more involved to come up with proper syntax for additional and
optional fields, without going to bt[/<type>]/addr=<addr>[/rhdl=<h>]
forms. ]
- I'm aware of libserialport's support for bluetooth ports. But IIUC
libsp expects users to explicitly configure these, while libble can
use them in transparent ways with just the server address spec. Users
still can either specify
conn=<rfcomm-port>
or conn=bt/rfcomm/<addr>
as they please.
- Rename the library to libbtserial or similar, since it deals with
BLE as well as BT Classic?
- Check whether support for other platforms can fit under the library's
public API. It's assumed that this is the case, as the API purposely
was designed to not encode specific assumptions of the first available
implementation.
- Implement support for other platforms. CMake can handle build variants
just fine, including platform dependent parts as well as common code.
The Linux implementation can either remain separate, or can use common
code that covers multiple platforms if such a library exists, can and
will be used, or gets implemented. (Searches on the 'Net suggest that
available libs are either written in Python or .Net, or authors think
that cross platform means "mobile Apple and Windows", the latter WIP
perhaps. Qt may support BT including BLE, but only on most recent
versions of these platforms, and is quite large a dependency for a
libsigrok driver or comm layer.)
- More recent BlueZ versions are said to support LE scan without the
need for root priviledges (which the currently implemented Linux
socket and HCI manipulation requires). A DBus interface can be used
instead. It's assumed that both approaches are required and a fallback
policy needs to get implemented, since neither approach is universally
available and usable in every setup.
- Add SPP as another BT Classic service? How does it relate to RFCOMM?