BlueST SDK is a multi-platform library (Android, iOS, and Linux supported) that allows easy access to the data exported by a Bluetooth Low Energy (BLE) device that implements the BlueST Protocol.
Documentation can be found here.
This version of the SDK is compatible with Python 3.5 and runs on a Linux system.
The BlueST SDK makes use of the bluepy Python interface to Bluetooth Low Energy on Linux.
$ sudo pip3 install bluepy
Moreover, it uses the concurrent.futures module to run pools of threads in background, that serve listeners' callbacks.
$ sudo pip3 install futures
The BlueST SDK currently suffers from the following limitations, which are intrinsic to the bluepy library:
The BlueST SDK can be installed through the Python pip package manager.
$ sudo pip3 install blue-st-sdk
Before running the application examples, please prepare your devices as described here below. They need to be equipped with BLE connectivity and a FW compatible with the BlueST Protocol.
Other application examples can be found within the EdgeST SDK for Linux, an IoT edge computing abstraction library for Linux gateways.
By default, on Linux, the Bluetooth protocol stack needs special privileges to interact with. Hence, run the application examples as super-user by following the steps here below:
$ git clone https://github.com/STMicroelectronics/BlueSTSDK_Python.git
$ sudo python3 example_ble_x.py
The library shows only the devices that have a vendor-specific field formatted in the following way:
Length | 1 | 1 | 1 | 1 | 4 | 6 |
---|---|---|---|---|---|---|
Name | Length | Field Type | Protocol Version | Device Id | Feature Mask | Device MAC (optional) |
Value | 0x07/0x0D | 0xFF | 0x01 | 0xXX | 0xXXXXXXXX | 0xXXXXXXXXXXXX |
The Field Length must be 7 or 13 bytes long.
The Device Id is a number that identifies the type of device:
In case you need to define your own custom boards, you should use Device Id values not yet assigned. Moreover, please note that values between 0x80 and 0xFF are reserved for ST Nucleo boards.
The feature mask is a bit field that provides information about the features exported by the board. Currently, bits are mapped in the following way:
Bit | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Feature | Analog | ADPCM Sync | Switch | Direction of arrival | ADPCM Audio | Microphone Level | Proximity | Luxmeter | Accelerometer | Gyroscope | Magnetometer | Pressure | Humidity | Temperature | Battery | Second Temperature |
Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Feature | CO Sensor | DC Motor | Stepper Motor | SD Logging | Beam forming | Accelerometer Event | Free Fall | Sensor Fusion Compact | Sensor Fusion | Motion Intensity | Compass | Activity Recognition | Carry Position | Proximity Gesture | MEMS Gesture | Pedometer |
To understand the way the data are exported by predefined features, please refer to the method Feature.extract_data(timestamp, data, offset)
within the features class definition.
Currently only a subset of the features is implemented: Switch, Proximity, Accelerometer, Gyroscope, Magnetometer, Pressure, Humidity, Temperature, Second Temperature, Stepper Motor, Proximity Gesture, Activity Recognition, ADPCM Audio, and ADPCM Sync. Moreover, other features not listed among the default 32-bit feature mask, are provided, like for example the Audio Scene Classification. Future releases of the Python SDK will cover all the abovementioned features.
The characteristics managed by the SDK must have a UUID as follows: XXXXXXXX-0001-11e1-ac36-0002a5d5c51b
.
The SDK scans all the services, searching for characteristics that match the pattern.
The first part of the UUID has bits set to "1" for each feature exported by the characteristics.
In case of multiple features mapped onto a single characteristic, the data must be in the same order as the bit mask.
A characteristic's data format must be the following:
Length | 2 | >1 | >1 | |
---|---|---|---|---|
Name | Timestamp | First Feature Data | Second Feature Data | ..... |
The first 2 bytes are used to communicate a timestamp. This is especially useful to recognize any loss of data.
Since the BLE packet maximum length is 20 bytes, the maximum size of a feature's data field is 18 bytes.
The SDK is compatible with the following ST firmware:
This is a singleton class that starts/stops the discovery process and stores the retrieved nodes.
Before starting the scanning process, it is also possible to define a new Device Id and to register/add new features to already defined devices.
The Manager notifies a new discovered node through the ManagerListener
class. Each callback is performed asynchronously by a thread running in background.
This class represents a remote device.
Through this class it is possible to recover the features exported by a node and read/write data from/to the device.
The node exports all the features whose corresponding bit is set to "1" within the advertising data message. Once the device is connected, scanning and enabling the available characteristics can be performed. Then, it is possible to request/send data related to the discovered features.
A node notifies its RSSI (signal strength) when created.
A node can be in one of following status:
Each callback is performed asynchronously by a thread running in background.
This class represents the data exported by a node.
Each feature has an array of Field
objects that describes the data exported.
Data are received from a BLE characteristic and contained in a Sample
class. The user is notified about new data through a listener.
Note that each callback is performed asynchronously by a thread running in background.
Available features can be retrieved from Features package.
Field
objects that describe the data exported by the feature.Feature.extract_data(timestamp, data, offset)
.Sample
object.Register the new feature: If you want to use BlueST's bitmask for features within the advertising data, please register the new feature before performing the discovery process, e.g.:
# Adding a 'MyFeature' feature to a Nucleo device and mapping it to a custom
# '0x10000000-0001-11e1-ac36-0002a5d5c51b' characteristic.
mask_to_features_dic = {}
mask_to_features_dic[0x10000000] = my_feature.MyFeature
try:
Manager.add_features_to_node(0x80, mask_to_features_dic)
except BlueSTInvalidFeatureBitMaskException as e:
print e
# Synchronous discovery of Bluetooth devices.
manager.discover(False, SCANNING_TIME_s)
Otherwise, you can register the feature after discovering a node and before connecting to it:
# Adding a 'FeatureHeartRate' feature to a Nucleo device and mapping it to
# the standard '00002a37-0000-1000-8000-00805f9b34fb' Heart Rate Measurement
# characteristic.
map = UUIDToFeatureMap()
map.put(uuid.UUID('00002a37-0000-1000-8000-00805f9b34fb'), feature_heart_rate.FeatureHeartRate)
node.add_external_features(map)
# Connecting to the node.
node.connect()
COPYRIGHT(c) 2019 STMicroelectronics
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.