Cross-platform Bluetooth API for Go and TinyGo.

Overview

Go Bluetooth

Go Bluetooth

PkgGoDev CircleCI

Go Bluetooth is a cross-platform package for using Bluetooth Low Energy hardware from the Go programming language.

It works on typical operating systems such as Linux, macOS, and Windows.

It can also be used running "bare metal" on microcontrollers produced by Nordic Semiconductor by using TinyGo.

The Go Bluetooth package can be used to create both Bluetooth Low Energy Centrals as well as to create Bluetooth Low Energy Peripherals.

Bluetooth Low Energy Central

A typical Bluetooth Low Energy Central would be your laptop computer or mobile phone.

This example shows a central that scans for peripheral devices and then displays information about them as they are discovered:

package main

import (
	"tinygo.org/x/bluetooth"
)

var adapter = bluetooth.DefaultAdapter

func main() {
	// Enable BLE interface.
	must("enable BLE stack", adapter.Enable())

	// Start scanning.
	println("scanning...")
	err := adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
		println("found device:", device.Address.String(), device.RSSI, device.LocalName())
	})
	must("start scan", err)
}

func must(action string, err error) {
	if err != nil {
		panic("failed to " + action + ": " + err.Error())
	}
}

Bluetooth Low Energy Peripheral

A typical Bluetooth Low Energy Peripheral would be a temperature sensor or heart rate sensor.

This example shows a peripheral that advertises itself as being available for connection:

package main

import (
	"time"

	"tinygo.org/x/bluetooth"
)

var adapter = bluetooth.DefaultAdapter

func main() {
  	// Enable BLE interface.
	must("enable BLE stack", adapter.Enable())

  	// Define the peripheral device info.
	adv := adapter.DefaultAdvertisement()
	must("config adv", adv.Configure(bluetooth.AdvertisementOptions{
		LocalName: "Go Bluetooth",
  	}))
  
  	// Start advertising
	must("start adv", adv.Start())

	println("advertising...")
	for {
		// Sleep forever.
		time.Sleep(time.Hour)
	}
}

func must(action string, err error) {
	if err != nil {
		panic("failed to " + action + ": " + err.Error())
	}
}

Current support

Linux macOS Windows Nordic Semi
API used BlueZ CoreBluetooth WinRT SoftDevice
Scanning ✔️ ✔️ ✔️ ✔️
Connect to peripheral ✔️ ✔️ ✔️
Write peripheral characteristics ✔️ ✔️ ✔️
Receive notifications ✔️ ✔️ ✔️
Advertisement ✔️ ✔️
Local services ✔️ ✔️
Local characteristics ✔️ ✔️
Send notifications ✔️ ✔️

Linux

Go Bluetooth support for Linux uses BlueZ via the D-Bus interface thanks to the https://github.com/muka/go-bluetooth package. This should work with most distros that support BlueZ such as Ubuntu, Debian, Fedora, and Arch Linux, among others.

Linux can be used both as a BLE Central or as a BLE Peripheral.

Installation

You need to have a fairly recent version of BlueZ, for example v5.48 is the latest released version for Ubuntu/Debian.

sudo apt update
sudo apt install bluez

Once you have done this, you can obtain the Go Bluetooth package using Git:

git clone https://github.com/tinygo-org/bluetooth.git

Compiling

After you have followed the installation, you should be able to compile/run the "scanner" test program:

cd bluetooth
go run ./examples/scanner

macOS

Go Bluetooth support for macOS uses the CoreBluetooth libraries thanks to the https://github.com/JuulLabs-OSS/cbgo package.

As a result, it should work with most versions of macOS, although it will require compiling using whatever specific version of XCode is required by your version of the operating system.

The macOS support only can only act as a BLE Central at this time, with some additional development work needed for full functionality.

Installation

In order to compile Go Bluetooth code targeting macOS, you must do so on macOS itself. In other words, we do not currently have cross compiler support. You must also have XCode tools installed:

xcode-select --install

Once you have done this, you can obtain the Go Bluetooth package using Git:

git clone https://github.com/tinygo-org/bluetooth.git

Compiling

After you have followed the installation, you should be able to compile/run the "scanner" test program:

cd bluetooth
go run ./examples/scanner

Windows

Go Bluetooth support for Windows uses the WinRT Bluetooth interfaces by way of the https://github.com/tinygo-org/bluetooth/winbt package that is part of this package.

The Windows support is still experimental, and needs additional development to be useful. At this time, it can only be used to perform scanning operations as a BLE Central.

For specifics please see https://github.com/tinygo-org/bluetooth/issues/13

Installation

Once you have done this, you can obtain the Go Bluetooth package using Git:

git clone https://github.com/tinygo-org/bluetooth.git

Compiling

After you have followed the installation, you should be able to compile/run the "scanner" test program:

cd bluetooth
go run .\examples\scanner

Nordic Semiconductor

Go Bluetooth has bare metal support for several chips from Nordic Semiconductor that include a built-in Bluetooth Low Energy radio.

This support requires compiling your programs using TinyGo.

You must also use firmware provided by Nordic Semiconductor known as the "SoftDevice". The SoftDevice is a binary blob that implements the BLE stack. There are other (open source) BLE stacks, but the SoftDevices are pretty solid and have all the qualifications you might need. Other BLE stacks might be added in the future.

The Nordic Semiconductor SoftDevice can be used both as a BLE Central or as a BLE Peripheral, depending on which chip is being used. See the "Supported Chips" section below.

Installation

You must install TinyGo to be able to compile bare metal code using Go Bluetooth. Follow the instructions for your operating system at https://tinygo.org/getting-started/

Once you have installed TinyGo, you can install the Go Bluetooth package by running:

git clone https://github.com/tinygo-org/bluetooth.git

Check your desired target board for any additional installation requirements.

Adafruit "Bluefruit" boards

The line of "Bluefruit" boards created by Adafruit already have the SoftDevice firmware pre-loaded. This means you can use TinyGo and the Go Bluetooth package without any additional steps required. Supported Adafruit boards include:

After you have installed TinyGo and the Go Bluetooth package, you should be able to compile/run code for your device.

For example, this command can be used to compile and flash an Adafruit Circuit Playground Bluefruit board with the example we provide that turns it into a BLE server to control the built-in NeoPixel LEDs:

tinygo flash -target circuitplay-bluefruit ./examples/circuitplay

There are other boards with TinyGo support that also use the same UF2 bootloader with pre-loaded SoftDevice. They include:

BBC micro:bit

Version 1

The BBC micro:bit uses an nRF51 chip with a CMSIS-DAP interface.

You will need to install OpenOCD (http://openocd.org/) to flash the board.

First, flash the SoftDevice firmware by copying the .hex file to the device. For example (on Linux):

cd bluetooth
cp ./s110_nrf51_8.0.0/s110_nrf51_8.0.0_softdevice.hex /media/yourusername/MICROBIT/

Once you have copied the SoftDevice firmware to the BBC micro:bit, you can then flash your TinyGo program:

tinygo flash -target=microbit-s110v8 ./examples/heartrate

Version 2

The BBC micro:bit v2 uses an nRF52833 chip with a CMSIS-DAP interface.

Support for the v2 will be available soon.

Supported Chips

The following Nordic Semiconductor chips are currently supported:

  • nRF51822 with the S110 SoftDevice (version 8). This SoftDevice does not support all features (e.g. scanning).
  • nRF52832 with the S132 SoftDevice (version 6).
  • nRF52840 with the S140 SoftDevice (version 6 and 7).

Flashing the SoftDevice on Other Boards

To use a board that uses one of the above supported chips from Nordic Semiconductor, other then those already listed, you will probably need to install the SoftDevice firmware on the board yourself in order to use it with TinyGo and the Go Bluetooth package.

Flashing the SoftDevice can sometimes be tricky. If you have nrfjprog installed, you can erase the flash and flash the new BLE firmware using the following commands. Replace the path to the hex file with the correct SoftDevice, for example s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex for S132 version 6.

nrfjprog -f nrf52 --eraseall
nrfjprog -f nrf52 --program path/to/softdevice.hex

After that, don't reset the board but instead flash a new program to it. For example, you can flash the Heart Rate Sensor example using tinygo (modify the -target flag as needed for your board):

tinygo flash -target=pca10040-s132v6 ./examples/heartrate

Flashing will normally reset the board.

API stability

The API is not stable! Because many features are not yet implemented and some platforms (e.g. Windows and macOS) are not yet fully supported, it's hard to say what a good API will be. Therefore, if you want stability you should pick a particular git commit and use that. Go modules can be useful for this purpose.

Some things that will probably change:

  • Add options to the Scan method, for example to filter on UUID.
  • Extra options to the Enable function, to request particular features (such as the number of peripheral connections supported).

This package will probably remain unstable until the following has been implemented:

  • Scan filters. For example, to filter on service UUID.
  • Bonding and private addresses.
  • Full support for all features at least two desktop operating systems.
  • Maybe some Bluetooth Classic support, such as A2DP.

Contributing

Your contributions are welcome!

Please take a look at our CONTRIBUTING.md document for details.

Frequently Asked Questions

Q. Where can I get an introduction to Bluetooth Low Energy, GAP, GATT, etc.?

A. Please see this excellent article from our friends at Adafruit: https://learn.adafruit.com/introduction-to-bluetooth-low-energy

Q. What is a client and server in BLE?

A. Please see https://devzone.nordicsemi.com/f/nordic-q-a/71/what-is-a-client-and-server-in-ble

Q. Can a device be both a GATT client and GATT server?

A. Yes, but this is not currently supported by Go Bluetooth. Current support is either to act as a central in client mode, or as a peripheral in server mode.

License

This project is licensed under the BSD 3-clause license, see the LICENSE file for details.

The SoftDevices from Nordic are licensed under a different license, check the license file in the SoftDevice source directory.

Issues
  • nrf52840: Scan not working as expected

    nrf52840: Scan not working as expected

    Took me a while to actually report this, because I thought it had to be some problem on my machine, but after testing on another system, I think it is something.

    I am currently unable to Scan() from the three different nrf52840 devices that I have tried (Itsybitsy-nRF52840, Circuit Playground Bluefruit, and Clue) using either the latest release or dev branches of both TinyGo and Bluetooth.

    I am able to run advertiser successfully, but not scan.

    One interesting note, is that when I tested the Clue using the test program I have with the attached display, sometimes after a very long period of time (10 or more minutes) it would suddenly start to work. However this was very inconsistent.

    nrf 
    opened by deadprogram 17
  • macos: initial support for scanning/connecting/write characteristics/notifications

    macos: initial support for scanning/connecting/write characteristics/notifications

    This PR adds the initial support for macOS with nothing more than scanning implemented.

    It is currently WIP so I am making it draft.

    opened by deadprogram 14
  • gattc: use GetUUID() to allow for bare metal use of short UUID.

    gattc: use GetUUID() to allow for bare metal use of short UUID.

    This PR adds a GetUUID() accessor to both DeviceService and DeviceCharacteristic to simplify use on bare metal with short UUIDs.

    opened by deadprogram 10
  • docs: how to flash board with UF2 bootloader?

    docs: how to flash board with UF2 bootloader?

    How exactly would one go about flashing a board such as the Circuit Playground Bluefruit with the needed code to run a TinyGo Bluetooth application?

    enhancement 
    opened by deadprogram 6
  • sd: unable to run scanner example

    sd: unable to run scanner example

    When I try to run the scanner example with -target circuitplay-bluefruit, the call to adaptor.Scan() results in a crash. The message itself seems to be obscured, nothing comes thru except the character p which I perhaps assume might be due to a panic getting lost?

    enhancement 
    opened by deadprogram 6
  • Arduino compat

    Arduino compat

    Is this library compatible with Arduino's at all? Apologies if this is a silly question!

    opened by EwanValentine 6
  • adapter.DefaultAdvertisement undefined

    adapter.DefaultAdvertisement undefined

    adapter.DefaultAdvertisement undefined (type *bluetooth.Adapter has no field or method DefaultAdvertisement)

    duplicate 
    opened by andarm 6
  • adaptor/macos: handle adapter enable notifications before program ready

    adaptor/macos: handle adapter enable notifications before program ready

    This PR handles the case when CoreBluetooth sends the adapter enable notification before the event delegate is set to receive it.

    opened by deadprogram 5
  • nrf52: add support for S140 version 6

    nrf52: add support for S140 version 6

    This is used on the Adafruit Circuit Playground Bluefruit bootloader, for example.

    Depends on https://github.com/tinygo-org/tinygo/pull/1329.

    opened by aykevl 5
  • Support Arduino nina-fw

    Support Arduino nina-fw

    It appears that if you pull the right pin low when an ESP-32 module with the Arduino nina-fw (e.g., Arduino Nano IOT, Adafruit Metro M4 Airlift, Pyportal, etc) it will put the module into Bluetooth mode at startup:

    https://github.com/arduino/nina-fw/blob/fc6bd42754ecf8e32079f9f2f3bec22d177ce0bf/main/sketch.ino.cpp#L108

    it appears the same functionality also exists in the Adafruit fork: https://github.com/adafruit/nina-fw/blob/0e267bc8858f188f5ac7c1527d0554d8294ca756/main/sketch.ino.cpp#L95

    If the Bluetooth mode is enabled, instead of processing wifinina commands over SPI, the ESP32 instead will process BLE related commands over UART. I have not found documentation on the protocol, but it might be possible to distill it from the ArduinoBLE library :

    https://github.com/arduino-libraries/ArduinoBLE/tree/master/src/utility

    enhancement help wanted 
    opened by bgould 0
  • 16bits UUID byte format on macos is different from other platforms.

    16bits UUID byte format on macos is different from other platforms.

    DIS service discovered UUID on macos: 180a0000-0000-0000-0000-000000000000

    DIS service discovered UUID on others: 0000180a-0000-1000-8000-00805f9b34fb

    specification: 128_bit_value = 16_bit_value * 2^96 + Bluetooth_Base_UUID

    macos 
    opened by nobonobo 2
  • Connection not working on nRF52840-DK

    Connection not working on nRF52840-DK

    I have flashed the heart rate example to a nRF52840-DK) board, and am unable to get anything to connect. It seems that they get the initial advertised services, but the connection eventually times out. Not sure what you need from me, but happy to share whatever.

    nrf 
    opened by andrewrynhard 4
  • How to get ManufacturerData

    How to get ManufacturerData

    Hi guys!

    Excellent work you have done here, I'm wondering how to get Manufacturer Data at scanning time, I would really appreciate your help solving this.

    Best regards!

    enhancement 
    opened by temphiza 1
  • sd: use constants from C instead of magic numbers

    sd: use constants from C instead of magic numbers

    This change depends on https://github.com/tinygo-org/tinygo/pull/1896.

    opened by aykevl 1
  • ParseMac func macIndex counter bug

    ParseMac func macIndex counter bug

    If the mac address is valid macIndex should equals to -1

    https://github.com/tinygo-org/bluetooth/blob/28f9f4e69ea8116eb3f180ec9c050cf9d27aa82c/mac.go#L39

    bug 
    opened by ty2 1
  • microbit-v2: add instructions on how to install softdevice firmware

    microbit-v2: add instructions on how to install softdevice firmware

    Need to add instructions on how to install softdevice firmware on v2 board.

    opened by deadprogram 0
  • Device property changes

    Device property changes

    Hello, is there a reason why not to use util.MapToStruct() here:

    // gap_linux.go -> line 171
    case "org.freedesktop.DBus.Properties.PropertiesChanged":
        interfaceName := sig.Body[0].(string)
        if interfaceName != "org.bluez.Device1" {
    	    continue
        }
        changes := sig.Body[1].(map[string]dbus.Variant)
        props := devices[sig.Path]
        // This is the part I added
        err := util.MapToStruct(props, changes)
        if err != nil {
    	    panic(err)
        }
        // instead of this
        // for field, val := range changes {
        // 	switch field {
        // 	case "RSSI":
        // 		props.RSSI = val.Value().(int16)
        // 	case "Name":
        // 		props.Name = val.Value().(string)
        // 	case "UUIDs":
        // 		props.UUIDs = val.Value().([]string)
        // 	}
        // }
        callback(a, makeScanResult(props))
    }
    

    I added some fields to AdvertisementFields struct and they did not update, so I fixed it like this. But I was just wondering if there is a reason why I should't do this?

    Thanks.

    linux 
    opened by lacendarko 0
  • Device DiscoverServices empty on Mac

    Device DiscoverServices empty on Mac

    Using macOS 11.1. Sacnning and connecting to a peripheral works good but I don't get any services when trying to discover them. Anyone else that experiences the same problem? Some devices seem to work but not all.

    macos 
    opened by eripe970 2
  • Adapter.Connect is not thread-safe on Mac OS

    Adapter.Connect is not thread-safe on Mac OS

    When running adapter.Connect calls concurrently, I've noticed that connection attempts to a non-existent address sometimes successfully return with the data of other devices.

    Minimal repro:

    
    adapter := bluetooth.DefaultAdapter
    wg := sync.WaitGroup()
    
    retryConnect := func(addr bluetooth.Addresser, device *bluetooth.Device) {
      wg.Add(1)
      // Keep retrying until we successfully connect
      for {
        if d, err := adapter.Connect(addr, bluetooth.ConnectionParams{}); err == nil {
            *device = d
            break
        }
        println("Retrying connection to", addr)  
      }
      wg.Done()
    }
    
    var dev1, dev2 bluetooth.Device
    
    go retryConnection("addr1", &dev1)
    go retryConnection("addr2", &dev2)
    
    wg.Wait()
    
    // At this point, dev1 and dev2 may be swapped or the same device.
    

    In the Mac OS implementation of Adapter, newly connected devices are sent over a channel which is shared between all callers (Adapter.connectChan). In Adapter.Connect, we then unconditionally take the first device sent across this channel and return it.

    This can lead to a data race in the case where we have multiple goroutines connecting to different devices at once, resulting in adapter.Connect returning successfully with the wrong device.

    macos next-release 
    opened by erik 0
Releases(v0.3.0)
  • v0.3.0(Mar 6, 2021)

    • core
      • generate standard service and characteristic UUIDs from Nordic Semiconductor bluetooth numbers database
    • linux
      • downgrade to older version of go-bluetooth that appears to work correctly with BlueZ 5.50
    • macos
      • properly handle 16-bit UUIDs for service and characteristics in the unique format used by macOS
    • docs
      • add a few details on some newly supported boards
    • examples
      • use standard service and characteristic UUIDs
      • correct heart rate monitor data format
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Nov 22, 2020)

    • core
      • gattc: DeviceCharacteristic Read() implementation
      • gap: add Disconnect() to Driver
      • gap: change signature for Addresser interface Set() function to accept string and then parse it as needed
    • linux
      • update to latest version of go-bluetooth package for Linux
    • macos
      • handle case when adapter enable sends notification before event delegate is set
      • Document async Disconnect behaviour
    • examples
      • discover should only wait on startup on baremetal, since macOS does not like that
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Sep 17, 2020)

    0.1.0

    • linux
      • support for both central and peripheral operation
    • macos
      • support for both central and peripheral operation
    • windows
      • experimental support for both central scanning only
    • nordic semiconductor
      • support for both central and peripheral operation on nRF82840 and nRF52832
      • support for peripheral only on nRF51822
    Source code(tar.gz)
    Source code(zip)
Owner
TinyGo
Go compiler for small places. Microcontrollers, WebAssembly, and command-line tools. Based on LLVM.
TinyGo
A directory of hardware related libs, tools, and tutorials for Go

Go + hardware This repo is a directory of tools, packages and tutorials to let you introduce Go in your hardware projects. Why Go? Go can target platf

Jaana Dogan 1.2k Jul 19, 2021
Cross platform locale detection for Golang

go-locale go-locale is a Golang lib for cross platform locale detection. OS Support Support all OS that Golang supported, except android: aix: IBM AIX

Xuanwo 78 Jun 8, 2021
⚖️ A tool for transpiling C to Go.

A tool for converting C to Go. The goals of this project are: To create a generic tool that can convert C to Go. To be cross platform (linux and mac)

Elliot Chance 1.7k Jul 12, 2021
psutil for golang

gopsutil: psutil for golang This is a port of psutil (https://github.com/giampaolo/psutil). The challenge is porting all psutil functions on some arch

shirou 6.5k Jul 24, 2021
Dynamically generated Last.fm stats for your profile readme

GitHub Readme Last.fm Stats Dynamically generated last.fm stats in your profile readme Contents Usage Options Demo Development & Deployment Issues, Re

Rafael Wiska-Ilnicki 3 May 8, 2021
🤖🤝A tool to test and analyze storage and retrieval deal capability on the Filecoin network.

Dealbot A tool to test and analyze storage and retrieval deal capability on the Filecoin network. Getting Started Clone the repo and build: git clone

Filecoin 17 Jul 24, 2021
this is an api that execute your deno code and send you the output

this a simple api that execute your deno code and send you the output, has not limit per request example request: in deno: const rawResponse = await f

pai 12 Jul 16, 2021
Minimal UART client in Golang that dumps LPC1343 chips that are locked at CRP1.

Howdy y'all, This is a quick and dirty client for the UART bootloader of the LPC1343, and probably other bootloaders in that chip family. This client

Travis Goodspeed 11 Mar 11, 2021
sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine.

sigurls is a reconnaissance tool, it fetches URLs from AlienVault's OTX, Common Crawl, URLScan, Github and the Wayback Machine. DiSCLAIMER: fe

Alex Munene 128 May 22, 2021
Extremely flexible golang deep comparison, extends the go testing package, tests HTTP APIs and provides tests suite

go-testdeep Extremely flexible golang deep comparison, extends the go testing package. Latest news Synopsis Description Installation Functions Availab

Maxime Soulé 183 Jul 20, 2021
Sample app that prints the compute region it’s running on

This web application prints the Google Cloud datacenter it’s running on with information about where the datacenter is located (city, country and flag). It's used to demonstrate global load balancing capabilities of Google Cloud HTTPS Load Balancer, as it routes the request to the compute region closest to the visitor.

Google Cloud Platform 11 Jun 13, 2021
sigbypass4xx is a utility to automate well-know techniques used to bypass access control restrictions.

sigbypass4xx sigbypass4xx is a utility to automate well-know techniques used to bypass access control restrictions. Resources Usage Installation From

Signed Security 3 Jul 12, 2021
A tool to check problems about meta files of Unity

A tool to check problems about meta files of Unity on Git repositories, and also the tool can do limited autofix for meta files of auto-generated files.

DeNA 38 Jul 14, 2021
A super simple Lodash like utility library with essential functions that empowers the development in Go

A simple Utility library for Go Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This

Rahul Baruri 81 Jul 17, 2021