nicebadge/tutorial/ble/step3/main.go

151 lines
3.1 KiB
Go
Raw Normal View History

2026-04-18 11:01:06 +00:00
package main
// BLE scanner example.
// Scans for nearby BLE devices and shows their names, addresses and signal
// strength (RSSI) on the display. Press button A to clear the list.
import (
"image/color"
"machine"
"strconv"
"time"
"github.com/tinygo-org/bluetooth"
"tinygo.org/x/drivers/st7789"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freesans"
)
const maxDevices = 5
type bleDevice struct {
name string
addr string
rssi int16
}
var (
adapter = bluetooth.DefaultAdapter
display st7789.Device
devices [maxDevices]bleDevice
count int
)
var (
black = color.RGBA{0, 0, 0, 255}
cyan = color.RGBA{0, 200, 255, 255}
white = color.RGBA{255, 255, 255, 255}
yellow = color.RGBA{255, 220, 0, 255}
green = color.RGBA{0, 220, 100, 255}
gray = color.RGBA{150, 150, 150, 255}
)
func main() {
initDisplay()
btnA := machine.P1_06
btnA.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
must("enable BLE", adapter.Enable())
drawHeader()
// scan runs in a goroutine; found devices are stored and displayed in the main loop
go func() {
adapter.Scan(func(a *bluetooth.Adapter, result bluetooth.ScanResult) {
name := result.LocalName()
if name == "" {
name = result.Address.String()
}
// update existing entry if already seen, otherwise add new
found := false
for i := 0; i < count; i++ {
if devices[i].addr == result.Address.String() {
devices[i].rssi = result.RSSI
found = true
break
}
}
if !found && count < maxDevices {
devices[count] = bleDevice{
name: name,
addr: result.Address.String(),
rssi: result.RSSI,
}
count++
}
})
}()
for {
// button A clears the list
if !btnA.Get() {
count = 0
display.FillRectangle(0, 32, 240, 103, black)
time.Sleep(200 * time.Millisecond)
}
drawDevices()
time.Sleep(500 * time.Millisecond)
}
}
func initDisplay() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.P1_01,
SDO: machine.P1_02,
Frequency: 8000000,
Mode: 0,
})
display = st7789.New(machine.SPI0,
machine.P1_15, machine.P1_13, machine.P0_10, machine.P0_09)
display.Configure(st7789.Config{
Rotation: st7789.ROTATION_90,
Width: 135,
Height: 240,
RowOffset: 40,
ColumnOffset: 53,
})
display.FillScreen(black)
}
func drawHeader() {
tinyfont.WriteLine(&display, &freesans.Bold12pt7b, 10, 24, "BLE Scanner", cyan)
}
func drawDevices() {
// clear device list area
display.FillRectangle(0, 32, 240, 103, black)
if count == 0 {
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 10, 55, "No devices found...", gray)
return
}
for i := 0; i < count; i++ {
y := int16(52 + i*20)
name := devices[i].name
if len(name) > 16 {
name = name[:16]
}
rssi := " " + strconv.Itoa(int(devices[i].rssi)) + "dB"
// color by signal strength
c := white
if devices[i].rssi > -60 {
c = green
} else if devices[i].rssi > -80 {
c = yellow
}
tinyfont.WriteLine(&display, &freesans.Regular9pt7b, 5, y, name+rssi, c)
}
}
func must(action string, err error) {
if err != nil {
panic("failed to " + action + ": " + err.Error())
}
}