团队讨论bluetooth时,我会先把用途说清楚:适用于 Go 的跨平台蓝牙 API 和 TinyGo。团队若要把它用于软件开发,应先处理依赖、接口和异常处理往往比主路径更影响采用,否则试用结果很容易失真。短测时我会在隔离分支完成一个可回滚的小任务,并保留安装步骤、接口契约、测试结果和错误信息的结果,方便团队复盘。它对需要可检查开发流程而非单次演示的工程师更有价值,但正式采用前仍要复查许可证、近期提交和问题区回应。
开启蓝牙
Go 蓝牙是一个跨平台包,用于使用 Go 编程语言中的 低功耗蓝牙 硬件。
它适用于 Linux、macOS 和 Windows 等典型操作系统。
通过使用 TinyGo,它还可以用于在 Nordic Semiconductor 生产的微控制器或具有使用 蓝牙主机控制器的蓝牙协处理器的板上运行“裸机”接口(HCI)。
Go 蓝牙包可用于创建蓝牙低功耗中央设备以及蓝牙低功耗外设。
蓝牙低能耗中心
典型的蓝牙低能耗中心是您的笔记本电脑或手机。
此示例显示了一个扫描设备的中心,然后在发现它们时显示有关它们的信息:
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())
}
}
蓝牙低功耗外设
典型的蓝牙低功耗外设是温度传感器或心率传感器。
此示例显示了一个将自身通告为可用于连接的设备:
package main
import (
"context"
"time"
"tinygo.org/x/bluetooth"
)
var adapter = bluetooth.DefaultAdapter
func main() {
// Enable BLE interface.
must("enable BLE stack", adapter.Enable())
ctx, cancel := context.WithCancel(context.Background())
adapter.SetConnectHandler(func(device bluetooth.Device, connected bool) {
if connected {
println("device connected:", device.Address.String())
return
}
println("device disconnected:", device.Address.String())
cancel()
})
// 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())
// Stop advertising to release resources
defer adv.Stop()
println("advertising...")
<- ctx.Done()
}
func must(action string, err error) {
if err != nil {
panic("failed to " + action + ": " + err.Error())
}
}
目前支持
| Linux | macOS | 窗户 | 北欧半球 | ESP32 (NINA-FW) | CYW43439 (RP2040-W) | |
|---|---|---|---|---|---|---|
| API 已使用 | BlueZ | CoreBluetooth | WinRT | SoftDevice | HCI | HCI |
| 扫描 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 连接到设备 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 写入外设特性 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 接收通知 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 广告 | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 本地服务 | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 地方特色 | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 发送通知 | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Linux
Linux 的 Go 蓝牙支持通过 D-Bus 接口使用 BlueZ。这应该适用于大多数支持 BlueZ 的发行版,例如 Ubuntu、Debian、Fedora 和 Arch Linux 等。
Linux 既可以用作 BLE 中央设备,也可以用作 BLE 外设。
安装
您需要有 BlueZ 的最新版本,例如 v5.48 是 Ubuntu/Debian 的最新发布版本。
sudo apt update
sudo apt install bluez
完成此操作后,您可以使用 Git 获取 Go 蓝牙包:
git clone https://github.com/tinygo-org/bluetooth.git
编译
完成安装后,您应该能够 compile/run “扫描仪”测试程序:
cd bluetooth
go run ./examples/scanner
macOS
由于 cbgo 包的 https://github.com/tinygo-org/cbgo 分支,macOS 的 Go 蓝牙支持使用 CoreBluetooth 库。
因此,它应该适用于大多数版本的 macOS,尽管它需要使用您的操作系统版本所需的任何特定版本的 XCode 进行编译。
macOS 支持此时只能充当 BLE Central,需要一些额外的开发工作才能实现完整功能。
安装
为了编译针对 macOS 的 Go 蓝牙代码,您必须在 macOS 本身上执行此操作。换句话说,我们目前没有交叉编译器支持。您还必须安装 XCode 工具:
xcode-select --install
完成此操作后,您可以使用 Git 获取 Go 蓝牙包:
git clone https://github.com/tinygo-org/bluetooth.git
编译
完成安装后,您应该能够 compile/run “扫描仪”测试程序:
cd bluetooth
go run ./examples/scanner
故障排除
iTerm2 和蓝牙包存在一个已知问题。如果您收到类似 abort: trap 的消息,请尝试通过“系统设置”->“隐私和安全”->“蓝牙”手动将 iTerm2 列入白名单。
窗户
Windows 的 Go 蓝牙支持通过 https://github.com/saltosystems/winrt-go 包使用 WinRT 蓝牙 接口。
安装
仅需要 Go 编译器本身来编译针对 Windows 的 Go 蓝牙代码。
您可以使用Git获取Go蓝牙包:
git clone https://github.com/tinygo-org/bluetooth.git
编译
完成安装后,您应该能够 compile/run “扫描仪”测试程序:
cd bluetooth
go run .examplesscanner
北欧半导体
Go Bluetooth 为 Nordic Semiconductor 的多个芯片提供裸机支持,其中包括内置蓝牙低功耗无线电。
此支持需要使用 TinyGo 编译您的程序。
您还必须使用 Nordic Semiconductor 提供的名为“SoftDevice”的固件。 SoftDevice 是实现 BLE 堆栈的二进制 blob。还有其他(开源)BLE 堆栈,但 SoftDevices 非常可靠,并且具有您可能需要的所有资格。将来可能会添加其他 BLE 堆栈。
Nordic Semiconductor SoftDevice 既可以用作 BLE 中央设备,也可以用作 BLE 外设,具体取决于所使用的芯片。请参阅下面的“支持的芯片”部分。
安装
您必须安装 TinyGo 才能使用 Go 蓝牙编译裸机代码。按照 https://tinygo.org/getting-started/ 中适用于您的操作系统的说明进行操作
安装 TinyGo 后,您可以通过运行以下命令来安装 Go 蓝牙包:
git clone https://github.com/tinygo-org/bluetooth.git
检查您所需的目标板是否有任何其他安装要求。
Adafruit“Bluefruit”板
Adafruit 创建的“Bluefruit”板系列已预加载 SoftDevice 固件。这意味着您可以使用 TinyGo 和 Go 蓝牙包,无需任何额外步骤。支持的 Adafruit 板包括:
安装 TinyGo 和 Go 蓝牙软件包后,您应该能够为您的设备获取 compile/run 代码。
例如,此命令可用于编译和烧写 Adafruit Circuit Playground Bluefruit 板,我们提供的示例将其转换为 BLE 服务器来控制内置 NeoPixel LEDs:
tinygo flash -target circuitplay-bluefruit ./examples/circuitplay
Seeed Studio XIAO nRF52840
Seeed Studio 小nRF52840 使用 UF2 引导加载程序 并预加载 SoftDevice 固件,因此与 TinyGo 一起使用非常容易。
您可以像这样刷新 TinyGo 程序:
tinygo flash -target=xiao-ble ./examples/heartrate
具有 UF2 引导加载程序的其他板
还有其他支持 TinyGo 的板,它们使用相同的 UF2 引导加载程序并预加载 SoftDevice。它们包括:
BBC micro:bit
版本1
BBC micro:bit 使用带有 CMSIS-DAP 接口的 nRF51 芯片。
您需要安装 OpenOCD (http://openocd.org/) 来刷新板。
首先,通过将 .hex 文件复制到设备来刷新 SoftDevice 固件。例如(在 Linux 上):
cd bluetooth
cp ./s110_nrf51_8.0.0/s110_nrf51_8.0.0_softdevice.hex /media/yourusername/MICROBIT/
将 SoftDevice 固件复制到 BBC micro:bit 后,您就可以刷新 TinyGo 程序:
tinygo flash -target=microbit-s110v8 ./examples/heartrate
版本2
BBC micro:bit v2 使用带有 CMSIS-DAP 接口的 nRF52833 芯片。
您需要安装 OpenOCD (http://openocd.org/) 来刷新该板。
您可以将 BBC micro:bit v2 用作仅使用 S113 SoftDevice 的外设,或者使用 S140 提供中央和外设支持。请注意,S140 确实需要更多内存,留给用户程序的内存更少。
要使用 S113,请将 .hex 文件复制到设备来刷新 SoftDevice 固件。例如(在 Linux 上):
cd bluetooth
cp ./s113_nrf52_7.0.1/s113_nrf52_7.0.1_softdevice.hex /media/yourusername/MICROBIT/
请注意,您只需执行此操作一次。在完成下一步之前,请勿重置板上的电源。
现在您已将 SoftDevice 固件复制到 BBC micro:bit v2,您可以刷新您的 TinyGo 程序:
tinygo flash -target=microbit-v2-s113v7 -programmer=cmsis-dap ./examples/heartrate
要使用具有中央和外设支持的 S140,请将 .hex 文件复制到设备来刷新 SoftDevice 固件。例如(在 Linux 上):
cd bluetooth
cp ./s140_nrf52_7.3.0/s140_nrf52_7.3.0_softdevice.hex /media/yourusername/MICROBIT/
请注意,您只需执行此操作一次。在完成下一步之前,请勿重置板上的电源。
现在您已将 SoftDevice 固件复制到 BBC micro:bit v2,您可以刷新您的 TinyGo 程序:
tinygo flash -target=microbit-v2-s140v7 -programmer=cmsis-dap ./examples/heartrate-monitor
支持芯片
目前支持以下 Nordic Semiconductor 芯片:
在其他板上刷写SoftDevice
要使用使用上述 Nordic Semiconductor 支持的芯片之一(除已列出的芯片之外)的开发板,您可能需要自行在开发板上安装 SoftDevice 固件,以便将其与 TinyGo 和 Go 蓝牙包一起使用。
刷新 SoftDevice 有时会很棘手。如果您安装了 nrfjprog,则可以使用以下命令擦除闪存并刷新新的 BLE 固件。将十六进制文件的路径替换为正确的 SoftDevice,例如 S132 版本 6 的 s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex。
nrfjprog -f nrf52 --eraseall
nrfjprog -f nrf52 --program path/to/softdevice.hex
之后,不要重置开发板,而是向其刷新新程序。例如,您可以使用 tinygo 刷新心率传感器示例(根据您的主板需要修改 -target 标志):
tinygo flash -target=pca10040-s132v6 ./examples/heartrate
闪烁通常会重置主板。
ESP32 (NINA)
Go Bluetooth 为包含独立 ESP32 蓝牙低功耗无线电协处理器的板提供裸机支持。 ESP32 必须运行 Arduino 或 Adafruit nina_fw 固件。
Adafruit 和 Arduino 创建的多款开发板已预加载 nina-fw 固件。这意味着您可以使用 TinyGo 和 Go 蓝牙包,无需任何额外步骤。
目前支持的主板包括:
安装 TinyGo 和 Go 蓝牙软件包后,您应该能够为您的设备获取 compile/run 代码。
例如,此命令可用于编译和刷新 Arduino Nano RP2040 Connect 板,我们提供的示例将其转换为 BLE 外设,充当心率监视器:
tinygo flash -target nano-rp2040 ./examples/heartrate
如果您想了解有关 nina-fw 固件的更多信息,或者想要添加对其他 ESP32- 配备的板的支持,请参阅 https://github.com/arduino/nina-fw
CYW43439 (RP2040-W)
Go Bluetooth 为包含独立 CYW43439 蓝牙低功耗无线电协处理器的板提供裸机支持。
目前支持的主板包括:
安装 TinyGo 和 Go 蓝牙软件包后,您应该能够为您的设备获取 compile/run 代码。
例如,此命令可用于编译和刷新 Pico RP2040-W 板,我们提供的示例将其转换为 BLE 外设,充当心率监视器:
tinygo flash -target pico-w ./examples/heartrate
如果您想了解有关 cyw43439 支持的更多信息,请参阅 https://github.com/soypat/cyw43439
API 稳定性
API 还不稳定! 因为很多功能还没有实现,而且一些平台(e.g.Windows 和 macOS)还没有完全支持,所以很难说 API 会有多好。因此,如果你想要稳定性,你应该选择一个特定的 git 提交并使用它。 Go 模块可用于此目的。
有些事情可能会改变:
Scan 方法添加选项,例如过滤 UUID。Enable 函数的额外选项,用于请求特定功能(例如支持的外设连接数量)。在实现以下内容之前,该软件包可能会保持不稳定:
常见问题解答
问。在哪里可以获得低功耗蓝牙、GAP、GATT 等的介绍?
答:请参阅 Adafruit 的朋友们写的这篇精彩文章:https://learn.adafruit.com/introduction-to-bluetooth-low-energy
问。 BLE中的客户端和服务器是什么?
A、请参见https://devzone.nordicsemi.com/f/nordic-q-a/71/what-is-a-client-and-server-in-ble
问。一个设备可以同时作为 GATT 客户端和 GATT 服务器吗?
答:可以,但 Go 蓝牙目前不支持此功能。当前的支持是在客户端模式下充当中心,或者在服务器模式下充当设备。