Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
ble
 
 
 
 
 
 
 
 
 
 
 
 

BLE-ADAPTER-GO

A Go bluetooth adapter implementation utilizing BlueZ and DBUS that allows BLE devices to interact with the ClearBlade Platform.

Much of the code has been based off of the implementation found at https://github.com/ecc1/ble

Additional information regarding BlueZ and DBUS can be found at the following links: BlueZ - https://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc
DBUS - https://www.freedesktop.org/wiki/Software/dbus/

Operating System Dependencies

The BLE Adapter is only supported on Linux operating systems with the following specifications:

  • Linux - Minimum kernel version of 3.5 - http://www.bluez.org/release-of-bluez-5-0/
  • BlueZ - The minimum version of BlueZ with BLE support is 5.40. It is recommended to install at least BlueZ version 5.44 (5.54 is the most current version).

Cross compile Go for Raspberry Pi

GOOS=linux GOARCH=arm GOARM=6 go build

Status


The adapter currently supports the following:

  1. Discover BLE devices and forward device properties to the ClearBlade platform
  2. Pairing with BLE devices
  3. Cancelling pairing with BLE devices
  4. Removing (unpairing) BLE devices
  5. Connecting to BLE devices
  6. Disconnecting from BLE devices
  7. Reading characteristic values from BLE devices
  8. Writing characteristic values to BLE devices

ClearBlade Platform Dependencies

The BLE Adapter was constructed to allow BLE devices to communicate with a System defined in a ClearBlade Platform instance. Therefore, the BLE Adapter requires a System to have been created within a ClearBlade Platform instance.

Once a System has been created, artifacts must be defined within the ClearBlade Platform system to allow the BLE Adapter to function properly. At a minimum, the following artifacts MUST be created within a ClearBlade Platform System:

  • Auth --> Devices

    • A row representing the physical gateway/device the BLE Adapter will be executing on
    • The value specified in the name column will be used as the value of the deviceName argument specified in the BLE Adapter start-up command
    • The value specified in the active_key column will be used as the value of the password argument specified in the BLE Adapter start-up command
  • BLE_Adapter_Config

    • A data collection containing a single row
    • Provides the ability to specify runtime configuration options
  • BLE_Device_Filters

    • A data collection that provides the ability to dynamically pass BLE service advertisement uuids into the device discovery process, via Adapter.setDiscoveryFilter
    • Discovery filters provide a mechanism to target specific BLE devices
    • CAVEAT: Discovery filtering will only work if the BLE device specifies a service UUID in its advertisement payload.

BLE_Adapter_Config Schema

Column Name Column Data Type Column Description
publish_topic string The MQTT topic to use when publishing to the platform (the specified topic will be prepended with deviceName/, where deviceName is the value of the deviceName argument specified on the start-up command)
discovery_scan_seconds integer Specifies the length of time a BLE device discovery scan should run
discovery_pause_seconds integer Specifies the length of time to pause between BLE device discovery scans
handle_removed boolean Specifies whether or not the BLE adapter should handle DBUS InterfaceRemoved signals
handle_changed boolean Specifies whether or not the BLE adapter should handle DBUS PropertiesChanged signals

BLE_Device_Filters Schema

Column Name Column Data Type Column Description
ble_uuid string The service advertisement uuid, optionally broadcasted by a BLE device, to allow for limiting the BLE devices that are discovered by the BLE adapter
enabled boolean Specifies whether or not filtering should be enabled for the specified UUID

Usage

Starting the ble adapter

ble-adapter-go -systemKey <PLATFORM SYSTEM KEY> -systemSecret <PLATFORM SYSTEM SECRET> -deviceName <AUTH DEVICE NAME> -password <AUTH DEVICE PASSWORD> -platformURL <CB PLATFORM URL> -messagingURL <CB PLATFORM MESSAGING URL>

Where

systemKey

  • REQUIRED
  • The system key of the ClearBLade Platform System the BLE adapter connect to

systemSecret

  • REQUIRED
  • The system secret of the ClearBLade Platform System the BLE adapter connect to

deviceName

  • REQUIRED
  • The device name the BLE adapter will use to authenticate to the ClearBlade Platform
  • Requires the device to have been defined in the Auth - Devices collection within the ClearBlade Platform System

password

  • REQUIRED
  • The password the BLE adapter will use to authenticate to the platform with.
  • Requires the device to have been defined in the Auth - Devices collection within the ClearBlade Platform System
  • In most cases the active_key of the device will be used as the password

platformURL

  • The url of the ClearBlade Platform instance the BLE Adapter will connect to
  • OPTIONAL
  • Defaults to http://localhost:9000

messagingURL

  • The MQTT url of the ClearBlade Platform instance the BLE Adapter will connect to
  • OPTIONAL
  • Defaults to localhost:1883

Configuration

The BLE adapter can be configured by changing the values specified within the row contained in the BLE_Adapter_Config data collection within the ClearBlade Platform. Changes made to any values will be applied prior to the start of a subsequent discovery scan.

Interacting with BLE Devices

The BLE Adapter provides the ability to interact with BLE devices: connect, disconnect, pair, read data, write data, etc. In order to interact with a ble device, a JSON message containing command details must be published, via MQTT, to the ClearBlade Platform MQTT message broker (or a ClearBlade Edge message broker).

JSON Message Format

The JSON message format expected by the BLE Adapter is as follows:

{
	"command": "write",
	"deviceAddress": "00:0B:57:36:73:9F",
	"devicePath": "/org/bluez/hci0/dev_00_0B_57_36_73_9F",
	"gattCharacteristic": "FCB89C40-C603-59F3-7DC3-5ECE444A401B",
	"gattCharacteristicValue": [12, 23, 43, 45],
	"stayConnected": true
}

command

  • The command to execute on the device. The command should be one of:
    • pair
    • remove
    • connect
    • disconnect
    • read
    • write
    • cancelPairing

deviceAddress

  • The device MAC address
  • Contained within the mac_address column of the BLE_Devices data collection within the ClearBlade Platform

devicePath

  • The DBUS object path
  • Can be determined by utilizing a utility such as D Feet
  • Contained within the JSON stored in the device_json column of the BLE_Devices data collection within the ClearBlade Platform

gattCharacteristic

  • GATT Characteristic UUID

gattCharacteristicValue

  • The value to of the specified gattCharacteristic
  • Must be specified as an array of 8-bit integers (translates to a byte array in lower level programming languages)
    • [12, 248, 255]
  • Returned in the response payload for read commands
  • Required as input for write commands

stayConnected

  • Should the BLE adapter in the linux operating system remain connected to the BLE device after the command runs?
  • true|false
  • The default value, if not specified, is false

Sending BLE Command Requests

To send a command request to a BLE device, JSON data in the format specified above should be published to the ClearBlade Platform or a ClearBlade Edge message broker. The MQTT topic name to publish to MUST be {Device Name}/bleadapter/bledevice/command, where {Device Name} is the value of the deviceName argument specified in the BLE Adapter start-up command.

BLE Command Responses

Responses to BLE commands will be published back to the ClearBlade Platform or ClearBlade Edge, thus allowing code triggers and code services to act on those responses. The responses will be published as a JSON payload. The JSON payload representing the response is a copy of the request payload with additional err and response members added. The err member is a boolean indicator denoting whether an error occurred. The response member is a string providing a description of the outcome of the command.

{
	"command": "write",
	"deviceAddress": "00:0B:57:36:73:9F",
	"devicePath": "/org/bluez/hci0/dev_00_0B_57_36_73_9F",
	"gattCharacteristic": "FCB89C40-C603-59F3-7DC3-5ECE444A401B",
	"gattCharacteristicValue": [12, 23, 43, 45],
	"stayConnected": true,
  "err": false,
  "response": "BLE command write executed successfully"
}

Setup


Tested with

  • golang 1.8 (minimum v1.6)
  • bluez bluetooth v5.44 and v5.45
  • raspbian and hypirot (debian 8) armv7 4.4.x

Upgrading BlueZ

These steps were compiled together from multiple sources obtained through numerous internet searches. The main source of information was taken from:

https://www.element14.com/community/community/stem-academy/microbit/blog/2016/09/16/1-microbit-1-raspberry-pi-3-1-bluez-upgrade-1-huge-headache

Install BlueZ Dependencies

  • sudo apt-get update
  • sudo apt-get install –y bluetooth bluez-tools build-essential autoconf glib2.0 libdbus-1-dev libudev-dev libical-dev libreadline-dev
Potential Errors Encountered
   Error with "sudo apt-get install glib2.0"  
   Processing triggers for man-db (2.7.0.2-5) ...  
   /usr/bin/mandb: can't rename /var/cache/man/2111 to /var/cache/man/index.db: Read-only file system  
   /usr/bin/mandb: can't remove /var/cache/man/2111: Read-only file system  
   /usr/bin/mandb: can't chmod /var/cache/man/index.db: Read-only file system  
   /usr/bin/mandb: can't remove /var/cache/man/index.db: Read-only file system  
   /usr/bin/mandb: warning: can't update index cache /var/cache/man/index.db: Read-only file system  
   fopen: Read-only file system  
   dpkg: unrecoverable fatal error, aborting:  
    unable to flush updated status of 'man-db': Read-only file system  
   E: Sub-process /usr/bin/dpkg returned an error code (2)  
   E: Failed to write temporary StateFile /var/lib/apt/extended_states.tmp
Resolution

Issue the following commands:

  • sudo mandb
   Purging old database entries in /usr/share/man...  
   Processing manual pages under /usr/share/man...  
   fopen: Read-only file system
  • sudo apt-get install libglib2.0-dev
    In the event of a __E: dpkg was interrupted__ error, execute: sudo dpkg –configure –a to correct the problem

Install BlueZ

Install the appropriate version of BlueZ (5.45 is currently the most recent version) by issuing the following commands at a terminal prompt:

  • wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz
  • tar xf bluez-5.45.tar.xz
  • cd bluez-5.45
  • ./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental --enable-maintainer-mode
  • make
  • sudo make install

Post Installation Configuration

Additional steps are needed in order to ensure BlueZ operates correctly when working with BLE devices and DBUS.

Enable Experimental Support

Enable experimental support in the bluetooth daemon (this enables BLE)

  • sudo sed -i '/^ExecStart.*bluetoothd\s*$/ s/$/ --experimental/' /lib/systemd/system/bluetooth.service
Link to Bluetooth Firmware

Raspbian installs Bluetooth firmware in a directory not recognized by Bluez. A symbolic link needs to be created so that BlueZ can accurately find the Bluetooth firmware.

  • sudo ln -s /lib/firmware /etc/firmware
Enable Bluetooth on Boot

Enable Bluetooth to load during system boot, then reload daemons to load it without rebooting, or just reboot after enabling it.

  • sudo systemctl enable bluetooth
  • sudo systemctl daemon-reload
Apply permissions

The following command will need to be executed for each user that will be accessing Bluetooth:
sudo usermod -G bluetooth -a pi

  • Where “pi” is the username in the example above. Replace “pi” with the username of any user who will need to be able to access Bluetooth.

When executing code (specifically GoLang), the following error was encountered when attempting to make a connection to DBUS:

Rejected send message, 2 matched rules; type="method_call", sender=":1.6"  
(uid=1000 pid=1031 comm="./ble-adapter-go -activeKey 1234567890 -deviceName")  
interface="org.freedesktop.DBus.ObjectManager" member="GetManagedObjects" error name="(unset)"  
requested_reply="0" destination="org.bluez"  
(uid=0 pid=624 comm="/usr/libexec/bluetooth/bluetoothd --experimental ")  

In order to rectify the issue, the following steps must be performed:

  1. edit /etc/dbus-1/system.d/bluetooth.conf
  2. Take the section <policy user="root"> and duplicate it for the user that the code is executing under (pi is assumed). Otherwise, all BLE code will need to be executed using sudo
   <policy user="pi">  
     <allow own="org.bluez"/>  
     <allow send_destination="org.bluez"/>  
     <allow send_interface="org.bluez.Agent1"/>  
     <allow send_interface="org.bluez.MediaEndpoint1"/>  
     <allow send_interface="org.bluez.MediaPlayer1"/>  
     <allow send_interface="org.bluez.ThermometerWatcher1"/>  
     <allow send_interface="org.bluez.AlertAgent1"/>  
     <allow send_interface="org.bluez.Profile1"/>  
     <allow send_interface="org.bluez.HeartRateWatcher1"/>  
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>  
     <allow send_interface="org.bluez.GattCharacteristic1"/>  
     <allow send_interface="org.bluez.GattDescriptor1"/>  
     <allow send_interface="org.freedesktop.DBus.ObjectManager"/>  
     <allow send_interface="org.freedesktop.DBus.Properties"/>  
   </policy>
Reboot

Reboot after making these changes. sudo reboot

Other Errors Encountered
2017/06/13 21:48:49 pi: setting discovery filter [32F9169F-4FEB-4883-ADE6-1F0127018DB3]  
Error setting discovery filter: %s Method "SetDiscoveryFilter"   
with signature "a{sv}" on interface "org.bluez.Adapter1" doesn't exist
Possible Solution

Upgrade BlueZ to version 5.43 at the minimum

Todo


  • Add unit tests
  • Add and generate docs with examples

About

GoLang BLE Adapter utilizing DBUS

Resources

License

Releases

No releases published

Packages

No packages published

Languages